以下是问题代码:
#include<iostream>
using namespace std;
class baseClass
{
public:
int objID;
baseClass()
{
cout << "(1) Default constructor" << objID << endl;
}
baseClass(int ID) // constructor
{
objID = ID;
cout << "(2) Constructing base object with ID: " << objID << endl;
}
};
class derivedClass : public baseClass
{
public:
derivedClass(int ID)
{
baseClass(10); // Line 1
//baseClass(ID); // Line 2
cout << "(4) Constructing derived object with ID: " << objID << endl;
}
};
int main(int argc, char** argv)
{
derivedClass dcObj(1);
return 0;
}
我遇到的问题是在derivedClass构造函数中使用第2行。它给我一个错误,我正在重新设计一个形式参数。我知道这是因为编译器认为我声明了一个名为&#34; ID&#34;的变量。类型为baseClass。我知道我应该在初始化列表中调用它。
但我的问题是为什么第1行工作?编译器将第1行解释为具有值10的baseClass对象的实例化。那么为什么第2行不起作用。我在这两种情况下都传递了一个int。编译器如何区分这两者。
答案 0 :(得分:1)
第1行正在运行,因为baseClass
有一个默认构造函数baseClass()
,在您创建derivedClass
实例时会自动调用它。您在第1行中对baseClass(10)
的调用会创建一个类型为baseClass
的临时对象,该对象从未使用过。选择此调用是因为10
不是有效的变量名,因此它被解释为函数的参数。
答案 1 :(得分:1)
这是一条旧的规则,继承自C,它尽力驱动程序员疯狂:
如果它可以是声明,则将其视为声明。
再加上C ++允许您在许多地方插入冗余括号 - int (x);
是一个有效的变量声明 - 这意味着
baseClass(ID);
被视为
baseClass ID;
(现阶段没有检查&#34; ID&#34;已经意味着什么,这只是语法。)
在后期阶段,当参数&#34; ID&#34;众所周知,这将成为一种重新定义。
另一方面,
baseClass 10;
可能不是声明,所以它意味着
baseClass(10);
构造一个未命名的baseClass
实例并立即将其抛弃。
答案 2 :(得分:1)
行的解释
baseClass(ID);
作为声明可以追溯到标准。来自C ++ Draft Standard N3337(强调我的):
6.8歧义解决方案
1语法中涉及表达式语句和声明的含糊不清:带有函数式显式类型转换(5.2.3)的表达式语句它的最左边的子表达式与第一个声明符以a开头的声明无法区分(。在这些情况下声明是声明。 [注意:要消除歧义,可能必须检查整个语句以确定如果它是表达式语句或声明。这消除了很多例子的歧义。
答案 3 :(得分:0)
编译器无法识别您调用衍生物, 他只是试图创建参数,而对于ID,他试图创建一个名为ID的变量,而对于10,他只是创建一个无名的临时对象。
答案 4 :(得分:0)
CASE_1: -
baseClass(ID);
这会给你一个错误,因为它被编译器解释为
baseClass ID; <<< You're redefining ID.
CASE_2: -
baseClass(10);
由于baseClass 10
解释是无意义的,编译器会将其视为构造函数调用。