在对象中构造对象

Constructing an object within an object

本文关键字:对象      更新时间:2023-10-16

我在类中声明了一个对象 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);
}

这给出了错误:只能调用一个函数。 我的问题是,如何在另一个对象中拥有一个对象,该对象可以由外部对象构造函数初始化。

您应该使用成员初始值设定项列表初始化数据成员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不是。

成员初始值设定项列表仅用于此目的。它们用于调用成员的构造函数,而不是分配它们。如果默认构造然后分配比直接构造慢,这可能会快得多。在几乎所有情况下,都应该使用它们而不是赋值。使用它们来初始化基元没有任何性能优势(在这种情况下,这只是风格问题,所以我通常还是这样做)。

这就是使用成员初始值设定项列表编写构造函数的方式。

B::B(char _letter, int _num1, string _word)
: letter(_letter), a(_num1, _word) {}

这可以稍微改善。我们可以为参数指定与成员相同的名称。在这种情况下,编译器将执行"正确的操作"并使用参数初始化成员。这也避免了以下划线开头的标识符,这是一个单独的问题。

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 甚至可能会为您重新排序。