类成员是另一个类的实例

时间:2016-10-20 15:04:02

标签: c++

我想让一个类成员成为另一个类的实例。但我得到一个警告“警告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; }

我不明白这个警告,请有人解释一下吗?

5 个答案:

答案 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; 
}