我想让一个类成员成为另一个类的实例。但我得到一个警告“警告C4458:声明'x'隐藏类成员”并且代码不起作用。
class Ca {
int va = 5;
public:
Ca();
int getVa(void);
};
int Ca::getVa(void) {
return va;
};
class Cb {
Ca x;
public:
Cb();
int getCa(void);
};
Cb::Cb(void) {
Ca x; // instanciate Ca
}
int Cb::getCa(void) {
return x.getVa();
}
int main()
{
Cb cb; // instanciate Cb
int i = cb.getCa();
cout << "va = " << i << endl;
}
我不明白这个警告,请有人解释一下吗?
答案 0 :(得分:6)
警告就在这一行:
Cb::Cb(void) {
Ca x; // <<== Here
}
问题是Ca x
是与成员变量x
无关的局部变量。
如果您只需调用默认构造函数来初始化x
,则无需执行任何操作:C ++将自动为您执行此操作。如果您想将一些参数传递给Ca
的构造函数,请使用初始化列表:
Cb::Cb(int argForAsConstructor) : x(argForAsConstructor) {
// Empty body
}
冒号后的构造允许您初始化没有默认构造函数的成员变量。
答案 1 :(得分:3)
在类Cb定义中声明Ca x,然后在Cb构造函数中声明一个新变量,而不是使用已定义的变量。
答案 2 :(得分:2)
你有问题:
Cb::Cb(void) { Ca x; // instanciate Ca }
由于Ca x
已经被定义为类Cb
的数据成员,因此存在&#34;冲突&#34; 与您在上面定义的局部变量Cb
构造函数。 &#34;冲突&#34; 是本地变量Ca x
&#34;隐藏&#34; 数据成员Ca x
。虽然这段代码可以编译,但它非常容易出错,并且可以更好地避免这种情况。
如果您的目的是初始化Ca x
数据成员,则不必在Cb
默认构造函数中执行任何操作:C ++会自动执行初始化。因此,您只需删除Ca x;
构造函数中的Cb
行。
编辑正如@Jesper在评论中写道,我完全赞同他,因为这是C ++而不是 C,考虑从void
中删除SIGHUP
一个空的参数列表。
答案 3 :(得分:1)
您的班级x
在此处定义了名为Ca x;
的成员变量:
x
但是在构造函数中,您声明了一个名为Ca x; // instanciate Ca
的另一个变量:
{{1}}
虽然这在技术上很好,但是当您在类成员函数中引用变量时,当您按名称引用成员变量时,通常您想要引用成员变量,但是在此case,因为有一个同名的局部变量,你最后会引用局部变量。
这是一种非常常见的难以识别错误的方法,所以注意警告而不是重复名称是一个非常好的主意。
答案 4 :(得分:0)
如果你想在构造函数中实现Class,你可以像这样使用:
class Ca {
int va = 5;
public:
Ca();
int getVa(void);
};
int Ca::getVa(void) {
return va;
};
class Cb {
std::unique_ptr<Ca> x;
public:
Cb();
int getCa(void);
};
Cb::Cb(void) {
x.reset(new Ca()); // Instanciate (Requires c++03 or newer)
}
int Cb::getCa(void) {
return x->getVa();
}
int main()
{
Cb cb; // instanciate Cb
int i = cb.getCa();
cout << "va = " << i << endl;
}