据我所知,要初始化类中的引用成员变量,我必须使用参数化构造函数初始化成员变量来使用初始化列表。 另外我明白,不需要默认构造函数。
问题:
但我不明白为什么定义默认构造函数会引发编译错误? 在以下情况下,Isn编译器是否足够聪明以考虑参数化构造函数而不是抛出错误?
如果对上述问题有完全可信的答案那么为什么编译器会允许声明默认构造函数(没有定义)?它在这方面有什么不同?
class SomeClass
{
public:
//SomeClass(){} //THIS IS AN ISSUE
//SomeClass(); //THIS IS FINE THOUGH
SomeClass(int j):i(j){}
int& i;
};
int main()
{
SomeClass obj(2);
return 0;
}
我相信const成员函数的行为也是如此。参考和const成员变量的原因是否相同?
答案 0 :(得分:4)
为什么定义默认构造函数会引发编译错误?
不是您定义默认构造函数,而是默认构造函数的定义不会初始化i
。您必需初始化所有作为引用的成员变量,而您的空定义不会这样做。
这与您需要初始化引用变量的原因相同:
void foo() {
int &i; // error: declaration of reference variable 'i' requires an initializer
}
为什么编译器允许声明默认构造函数(没有定义)
因为定义是问题,而不是声明。例如,将不正确的构造函数定义移出类定义之外将产生相同的错误:
class SomeClass
{
public:
SomeClass();
int &i;
};
SomeClass::SomeClass() {} // error: constructor for 'SomeClass' must explicitly initialize the reference member 'i'
这两个示例的唯一问题是您没有初始化i
。
请注意以下将编译的示例。请注意,构造函数的声明不会更改,但定义会初始化i
。
int someGlobalInt;
class SomeClass
{
public:
SomeClass() : i(someGlobalInt) {}
int &i;
};
int someGlobalInt;
class SomeClass
{
public:
SomeClass();
int &i;
};
SomeClass::SomeClass() : i(someGlobalInt) {}
答案 1 :(得分:1)
编译器要求初始化所有引用。如果你定义一个什么都不做的默认构造函数,那么编译器就会抱怨,因为你没有初始化i
。如果你声明了默认构造函数,那么你还没有定义它,所以编译器没有问题。考虑一下:
class SomeClass
{
SomeClass(); // Compiler is fine with this
...
};
int someInt;
SomeClass::SomeClass(): i(someInt) {} // OK - i is initialized
您稍后定义了构造函数并初始化了i
。
答案 2 :(得分:0)
第一个是构造函数的实现,它无法对引用成员进行必要的初始化:
SomeClass(){}
第二个只是构造函数的声明。只要它没有被执行,缺乏实现就不是问题。只要没有实现,(可能)初始化失败不是问题:
SomeClass();
请注意,非参数化构造函数可以正确初始化引用成员,例如引用全局变量或静态变量。这对任何事情都没有用,但它是可能的。因此,对于编译器,第二个版本不是直接问题,并不一定表示其他地方的实际问题。