fanThomas
fanThomas

Reputation: 129

Class member being an instance of another class

I want to have a class member to be an instance of another class. But I get a warning "warning C4458: declaration of 'x' hides class member" and the code does not work.

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

I do not understand the warning, please could someone explain?

Upvotes: 1

Views: 6723

Answers (5)

cpatricio
cpatricio

Reputation: 457

If you wanna to instanciate Class in the constructor, you can use like this:

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

Upvotes: 0

Mr.C64
Mr.C64

Reputation: 42944

You have a problem here:

Cb::Cb(void) {
    Ca x;   // instanciate Ca
}

Since Ca x is already defined as data member of class Cb, there is a "conflict" with the local variable you defined above inside the Cb constructor. The "conflict" is that the local variable Ca x "hides" the data member Ca x. While this code would compile, it is very error prone, and this situation is better avoided.

If your intent was to initialize the Ca x data member, you don't have to do anything in Cb default constructor: C++ does the initialization automatically. So you can just remove the Ca x; line in Cb's constructor.

EDIT As @Jesper wrote in his comment, and I completely agree with him, since this is C++ and not C, consider eliminating the void from an empty parameter list.

Upvotes: 3

xaxxon
xaxxon

Reputation: 19761

Your class Cb has a member variable named x defined here:

Ca x;

But then in your constructor, you declare a different variable named x:

Ca x;   // instanciate Ca

While this is technically fine, when you reference a variable in a class member function, when you refer to a member variable by name, usually you want to refer to the member variable, but in this case, since there's a local variable with the same name you wind up referring to the local variable.

This is a VERY common way to get difficult to identify errors and so it is a very good idea to heed the warning and not duplicate the name.

Upvotes: 1

K Richardson
K Richardson

Reputation: 1710

You declare Ca x in the class Cb definition, then in the Cb constructor, you declare a new variable rather than using the one already defined.

Upvotes: 5

Sergey Kalinichenko
Sergey Kalinichenko

Reputation: 726579

The warning is on this line:

Cb::Cb(void) {
    Ca x;   // <<== Here
}

The problem is that Ca x is a local variable unrelated to member variable x.

If all you need is to call the default constructor to initialize x, you don't have to do anything: C++ will do it for you automatically. If you would like to pass some parameters to Ca's constructor, use initializer list:

Cb::Cb(int argForAsConstructor) : x(argForAsConstructor) {
    // Empty body
}

The construct after the colon lets you initialize members variables that do not have default constructors.

Upvotes: 8

Related Questions