我有一个在类内声明的对象A,我想在初始化对象B时初始化对象A:
class A{
private:
int num1;
string word;
public:
A(int,word);
};
A::A(int _num1, string _word){
num1 = num1;
word = _word;
}
class B{
private:
char letter;
A a;
public:
B(char,int,string)
};
B::B(char _letter, int _num1, string _word){
letter = _letter;
a(_num1, _word);
}
这给出了错误:只能调用一个函数。 我的问题是,我如何在另一个对象内部拥有一个可以由外部对象构造函数初始化的对象。
答案 0 :(得分:5)
您应使用member initializer list初始化数据成员a
,
B::B(char _letter, int _num1, string _word) : a(_num1, _word) {
letter = _letter;
}
或更佳
B::B(char _letter, int _num1, string _word) : letter(_letter), a(_num1, _word) {}
请注意,进入B
的构造函数主体时,a
必须已初始化。如果不使用上述成员初始化程序列表,则a
将尝试使用默认构造函数进行初始化,但是A
没有一个。并且a(_num1, _word);
只是试图调用a
,就好像它是一个函子,而a
不是。
答案 1 :(得分:4)
Member initializer lists仅用于此目的。它们用于调用成员的构造函数,而不是分配成员。如果默认构造然后分配比直接构造慢,则可以快很多。在几乎所有情况下,都应使用它们代替分配。使用它们初始化基元没有任何性能上的好处(在这种情况下,这只是样式问题,因此我通常还是这样做)。
这是使用成员初始化程序列表编写构造函数的方式。
B::B(char _letter, int _num1, string _word)
: letter(_letter), a(_num1, _word) {}
这可以稍微改善。我们可以为参数指定与成员相同的名称。在这种情况下,编译器将做“正确的事”,并使用参数初始化成员。这也避免了使用下划线which is a separate issue开头的标识符。
B::B(char letter, int num1, string word)
: letter(letter), a(num1, word) {}
关于成员初始化程序列表要注意的一件事是初始化的顺序。成员将按照在类中声明的顺序进行初始化。在这种情况下,letter
将在a
之前初始化。 初始化列表的顺序对初始化顺序没有影响。请考虑以下示例:
B::B(char letter, int num1, string word)
: a(num1, word), letter(letter) {}
这将先初始化letter
,然后初始化a
。这就是为什么您应确保顺序与类中声明的顺序相同的原因。如果将适当的警告标志传递给编译器,它将告诉您有关此信息,并且您的IDE甚至可能为您重新排序。