我正在尝试在类中实例化一个类,以便外部类包含内部类。
这是我的代码:
#include <iostream>
#include <string>
class Inner {
private:
std::string message;
public:
Inner(std::string m);
void print() const;
};
Inner::Inner(std::string m) {
message = m;
}
void Inner::print() const {
std::cout << message << std::endl;
std::cout << message << std::endl;
}
class Outer {
private:
std::string message;
Inner in;
public:
Outer(std::string m);
void print() const;
};
Outer::Outer(std::string m) {
message = m;
}
void Outer::print() const {
std::cout << message << std::endl;
}
int main() {
Outer out("Hello world.");
out.print();
return 0;
}
“Inner in”,是我尝试在内部包含内部,但是,当我编译时,我得到一个错误,即没有匹配函数来调用Inner :: Inner()。 我做错了什么?
感谢。
答案 0 :(得分:6)
您需要使用初始化列表来初始化类成员:
Inner::Inner(const std::string& m)
: message(m)
{
}
Outer::Outer(const std::string& m)
: in(m)
{
}
(请注意,我按照const
引用传递了字符串,这比按值传递它们要好。请参阅this answer了解如何传递函数参数。) 强>
这样,您可以准确指定应为类成员调用哪些构造函数。
如果未指定构造函数,则将隐式调用默认构造函数。稍后分配给对象将调用赋值运算符并覆盖默认构造函数初始化对象的任何内容。那是最好的浪费表现
由于我们的Inner
没有默认构造函数(声明任何构造函数阻止编译器自己定义默认构造函数),因此无法调用它,因此 需要 指定显式获取字符串的构造函数。
编辑:请注意,如果您有多个类成员,则会以逗号分隔所有这些成员:
Outer::Outer(const std::string& m) : in1(m), in2(m), in3() {}
请注意, 类成员初始化的顺序取决于它们在类定义 中的声明顺序,而不是它们在初始化列表中出现的顺序。最好不要依赖初始化顺序,因为在类定义中更改它会在构造函数的定义中创建一个非常微妙的错误。如果您无法避免,请在类成员声明之外发表评论:
class outer {
public:
outer(const inner& in)
: in_(in), rin_(in_) // depends on proper declaration order of in_ and rin_
{}
private:
inner in_; // declaration order matters here!1
inner& rin_; // (see constructor for details)
};
基类构造函数以相同的方式指定,它们在类成员之前初始化,也按基类列表中的声明顺序初始化。但是,虚拟基类在所有非虚基类之前初始化。
析构函数BTW总是以构造函数的相反顺序调用。你可以依靠它。
答案 1 :(得分:1)
由于Inner
没有默认构造函数,因此需要显式初始化它。正如@sbi指出的那样,这样做的方法是使用构造函数中的初始化列表。
答案 2 :(得分:-1)
您还可以向Inner添加一个不带参数的构造函数。由于您未在in
中明确初始化Outer
,因此它会隐式尝试调用它。如果in
是指针(Inner *in
),那么它会起作用。
基本上如果你写
Foo f;
在C ++中,它将调用默认构造函数(Foo::Foo()
)。