sdasdadas
sdasdadas

Reputation: 25096

Constructor Overloading in C++

My C++ overloading does not act as I assume it should:

#include "Node.h"
#include <iostream>

Node::Node()
{
    cout << "1" << endl;
    Node(Game(), 0.0);
}

Node::Node(double v)
{
    cout << "2" << endl;
    Node(Game(),v);
}

Node::Node(Game g, double v)
{
    cout << "3" << endl;
    numVisits = 0;
    value = v;
    game = g;
}

And the output from:

Node n(16);
cout << n.value << endl;

is 0, when it should be 16.

What am I doing incorrectly?

Upvotes: 32

Views: 88879

Answers (5)

Mu Qiao
Mu Qiao

Reputation: 7107

Node(Game(),v); in your constructor doesn't do what you expected. It just creates a temporary without using it and makes no effect. Then it immediately destructs that temporary when control flows over the ;.

The correct way is initializing the members in each constructor. You could extract their common code in a private init() member function and call it in each constructor like the following:

class Foo {
    public:
        Foo(char x);
        Foo(char x, int y);
        ...
    private:
        void init(char x, int y);
};

Foo::Foo(char x)
{
    init(x, int(x) + 3);
    ...
}

Foo::Foo(char x, int y)
{
    init(x, y);
    ...
}

void Foo::init(char x, int y)
{
    ...
} 

C++11 will allow constructors to call other peer constructors (known as delegation), however, most compilers haven't supported that yet.

Upvotes: 48

mister why
mister why

Reputation: 1987

In a nutshell:

#include <iostream>
#include "Node.h"

Node::Node()
    : game(Game()), value(0.), numVisits(0)
{
    std::cout << "1" << std::endl;
}

Node::Node(double v)
    : game(Game()), value(v), numVisits(0)
{
    std::cout << "2" << std::endl;
}

Node::Node(Game g, double v)
    : game(g), value(v), numVisits(0)
{
    std::cout << "3" << std::endl;
}

As everyone said, you cannot call a constructor overload from a constructor. Delegation is an upcomming feature we'll meet with C++11. It's not much text to type, don't be lazy.

Upvotes: 0

Tim Meyer
Tim Meyer

Reputation: 12600

You could do it like this, where init() is a private method:

#include "Node.h"
#include <iostream>

Node::Node()
{
    cout << "1" << endl;
    init(Game(), 0.0);
}

Node::Node(double v)
{
    cout << "2" << endl;
    init(Game(),v);
}

Node::Node(Game g, double v)
{
    cout << "3" << endl;
    init(g,v)
}

void Node::init(Game g, double v)
{
    numVisits = 0;
    value = v;
    game = g;
}

Upvotes: 2

Mahesh
Mahesh

Reputation: 34615

Node::Node(double v)
{
    cout << "2" << endl;
    Node(Game(),v);            // 1      
}
  1. Creates a nameless object, which does not persist beyond that expression. So, it is not affecting the original object's value upon which the single argument constructor is instantiated. You also need to understand that this temporary object is entirely different from the original constructing object.

However you can extend the life time of this temporary object by a const reference i.e.,

Node::Node(double v)
{
    cout << "2" << endl;
    const Node& extendTemporay = Node(Game(),v); 

    value = extendTemporary.value ;  // Just trivial example;
                                     // You can simply do it by value = v;               
}

Upvotes: 2

Praetorian
Praetorian

Reputation: 109089

The feature you're trying to use is called delegating constructors, which is part of C++0x. Using that syntax your second constructor becomes

Node::Node(double v)
: Node(Game(),v)
{
    cout << "2" << endl;
}

Upvotes: 20

Related Questions