16

One of the corner stones of OOP is reusing code instead of repeat it over and over. Thus, your projects shorten and get more readable.

C++ gives you all the tools you need to reuse methods instead of repeating the code. Although when it comes to constructors I do not know how to reuse them.

I am not talking of heritage or how to send a message to the father. I am talking about reusing the constructor of the class itself.

The analogy in JAVA is something like this:

public Foo() {
    this(0,0,0);//Not needed in this case, just to clarify
}

public Foo(Foo f){
    this(f.getA(), f.getB(), f.getC());
}

public Foo(int a, int b, int c) {
    this.a = a;
    this.b = b;
    this.c = c;
}

My question is, is there any syntaxis in C++ that allows you to do so?

eversor
  • 3,031
  • 2
  • 26
  • 46

4 Answers4

13

C++11 has added constructor delegation and constructor inheritance.

To inherit constructors, a using-declaration is required:

class Base { ... };

class Derived : public Base
{
    using Base::Base;
};

To delegate, use the ctor-initializer, but specify another constructor in the same class, instead of any subobjects (all base and member subobjects will be initialized by the constructor delegated to):

class Another : public Base
{
    int member;
    Another(int x)
        : Base(), member(x) // non-delegating constructor initializes sub-objects
    {}


    Another(void)
        : Another(5) // delegates -- other constructor takes care of Base and member
    {}
};

And perfect forwarding can also come in handy.

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
11

Others already answered about C++11, but for C++03 there's a possible workaround: using a base class with needed constructor(s).

struct foo_base {
    foo_base(int a, int b, int c) : a(a), b(b), c(c) { }
    int a, b, c;
};

struct foo : foo_base {
    foo() : foo_base(0, 0, 0) { }
    foo(const foo& other) : foo_base(other.a, other.b, other.c) { }
    foo(int a, int b, int c) : foo_base(a, b, c) { }
};

Of course, you need to consider whether it's worth the boilerplate for your purposes.

Cat Plus Plus
  • 125,936
  • 27
  • 200
  • 224
2

The generally accepted soultion for current compilers is to do this:

class Bar{
pubilc:    
Foo() {
   init(0,0,0);
}

Foo(const Foo &f){
  init(f.getA(), f.getB(), f.getC());
}

Foo(int a, int b, int c) {
  init(a,b,c);
}

private:

void init(int a, int b, int c){
  this->a = a;
  this->b = b;
  this->c = c;
}
};

While this may seem like over kill in this example, that is only because of the simplicity of the example. In a real world application this would actually bring benefits in terms of reduction of repeated code.

Kurtis Nusbaum
  • 30,445
  • 13
  • 78
  • 102
  • Sorry, java and c++ blur together for me sometimes. I edited my post so that it's entirely in valid c++ now assuming you have valid getA(), getB(), getC() functions. – Kurtis Nusbaum Oct 05 '11 at 21:19
  • 1
    `this.a` is invalid, and copy constructor should take const reference as an argument. – Cat Plus Plus Oct 05 '11 at 21:21
  • Woops, sorry. Thanks for catching that Cat Plus Plus. Just go ahead and fix it next time. – Kurtis Nusbaum Oct 05 '11 at 21:25
  • @Kurtis Nusbaum: Even if you had valid getA() would you use it? You have full accesses to all members of another object of the same type (it is assumed that you trust yourself to write good code). – Martin York Oct 06 '11 at 00:13
  • @LokiAstari Depends. I bet I could imagine some instances where getA() has some extra code in it that affects the state of the object and we'd want to get the value of a through that. – Kurtis Nusbaum Oct 06 '11 at 01:34
  • 1
    Members should be assigned in the *ctor-initializer* list, for one thing it's the only way to set `const` members. – Ben Voigt Oct 06 '11 at 02:39
1

OK C++11 covers what you need.

But your simple case has an easy solution:

/* This one is covered by providing default parameters see below.
public Foo() {
    this(0,0,0);//Not needed in this case, just to clarify
}

 This is done automatically by the compiler.
 You do not need to write any code for this:
public Foo(Foo f){
    this(f.getA(), f.getB(), f.getC());
}
The compiler generated version actually looks like this:
public Foo(Foo const& f)
    : a(f.a)
    , b(f.b)
    , c(f.c)
{}



*/

// Now you can use all three methods and they work fine:
public Foo(int a = 0, int b = 0, int c = 0)
    : a(a)
    , b(b)
    , c(c)
{}

F   f1;        // default construct no parameters: uses the three parameter version
F   f2(f1);    // Copy constructed. Generated by the compiler.
F   f3(1,2,3); // Nomal constructor
Martin York
  • 257,169
  • 86
  • 333
  • 562
  • I am generally against using default values for parameters if not _all_ the different permutations of how you can use it now make sense, i.e. now you have actually four ways to use `Foo(int,int,int)`, which possibly does not make sense. – Sebastian Mach Jul 25 '13 at 11:36