C++ 中呼叫不具參數的建構函式為什麼不能加圓括號?

RMAG news

在 C++ 中建立物件時, 如果是要使用預設的建構函式或是不具參數的建構函式時, 不能在變數名稱後面加上圓括號, 例如:

class MyClass {
public:
int i;

MyClass() {
// 預設 (不含參數) 的建構函式
}
};

int main() {
MyClass obj; // 正確
obj.i = 10;
return 0;
}

如果寫成以下這樣:

class MyClass {
public:
int i;

MyClass() {
// 預設 (不含參數) 的建構函式
}
};

int main() {
MyClass obj(); // 語法正確
obj.i = 10; // 這裡會出錯
return 0;
}

就會出現編譯錯誤:

C:Usersmeebocodecpptest.cpp: In function ‘int main()’:
C:Usersmeebocodecpptest.cpp:12:9: error: request for member ‘i’ in ‘obj’, which is of non-class type ‘MyClass()’
12 | obj.i = 10;
| ^

它的意思是 obj 並不是類別型態的變數, 所以無法讀取成員。你可能會覺得很奇怪, 但這是因為以下這一行:

MyClass obj(); // 語法正確

被編譯器解釋為宣告一個名稱為 obj、沒有參數, 且傳回值是 MyClass 類別物件的函式, 因此錯誤訊息中可以看到它認為 obj 是 MyClass() 型別, 也就是傳回 MyClass 類別物件, 沒有引數的函式, 函式當然就無法讀取成員。

對於 C++ 編譯器來說, 雖然同一行程式也可看成是要透過沒有參數的建構函式建立物件, 但它只能選擇其中一種解譯方式。如果把這一行當成是透過沒有引數的建構函式建立物件, 那實際上是要宣告一個沒有引數的函式時, 編譯器就無法正確判斷出來了。為了解決這個問題, 因此 C++ 的語法規定在呼叫沒有引數的建構函式時, 不能加上呼叫語法的圓括號, 否則就會視為是要宣告一個沒有引數的函式。