mchen
mchen

Reputation: 10156

Scoping issues when chaining class constructors

Why does the following not work when chaining constructors:

#include <iostream>
#include <vector>

class cls {
public:
    cls()           {cls(5);}       // want to resize v to 5
    cls(int n)      {v.resize(n);}
    std::vector<int> v;
};

int main(int argc, const char* argv[]) {
    cls x, y(5);
    std::cout << x.v.size() << std::endl;   // prints 0 <- expected 5
    std::cout << y.v.size();                // prints 5
    return 0;
}

Demo: http://ideone.com/30UBzS

I expected both objects to have a v of size 5. What's wrong?

Reason I want to do this is because writing separate cls() and cls(n) ctors would duplicate a lot of code.

Upvotes: 1

Views: 70

Answers (4)

user1764961
user1764961

Reputation: 693

Here is what you need:

class cls
{
public:
       cls()
       :
       v( 5 ){}               // create v that contains 5 elements ( each initialized to 0 ) - note: this is NOT resizing

        explicit cls( const int size )
        :
        v( size ){}
private:       
        std::vector<int> v;
};

Of course, if you need resizing feature on the living object, you will need a 'resize' method already mentioned in this thread.

Upvotes: 0

user2093113
user2093113

Reputation: 3560

Calling cls(5); inside of the cls::cls() constructor is not doing what you think it is doing. It is creating a temporary variable using the second cls constructor which is destroyed at ;.

You can use C++11's delegating constructors to achieve what you want:

cls() : cls(5) { }

If you don't have a compiler that supports C++11, you can pull the common initialisation out into another function, and have both constructors call that:

class cls {
public:
    cls()           { init(5); }
    cls(int n)      { init(n); }
    std::vector<int> v;
private:
    void init(int n) { v.resize(n); }
};

Upvotes: 2

stardust
stardust

Reputation: 5988

You should change

cls()  {cls(5);} 

to

cls()  {v.resize(5);} 

Otherwise you are creating new temporary cls in the constructor and ignoring it.


OR If you want to delegate the constructor (C++11) do it like this

cls() : cls(5)  {} 
//   ^^   ^
//        | use cls(int n)

delegated constructor are allowed only in the member initialization list of a constructor.

Upvotes: 0

David G
David G

Reputation: 96810

cal(5) creates a completely different object, in fact it's a temporary meaning the object will be destroyed at the end of its encapsulation expression. Or it might not be called at all due to compiler optimization.

But with that aside, the constructor call only affects the temporary and not the original object calling the constructor.

If your intention was to make the code shorter, you should create a member function that does this (assuming your compiler doesn't support C++11, in which case you could simply use the Delegating Constructor feature):

class cls
{
    void resize(int n)
    {
        v.resize(n);
    }

    public:
        cls()           { resize(5); }
        cls(int n)      { resize(n); }
        std::vector<int> v;
};

Upvotes: 0

Related Questions