Многоразовые конструкторы C ++ - PullRequest
14 голосов
/ 06 октября 2011

Одним из краеугольных камней ООП является повторное использование кода, а не повторение его снова и снова. Таким образом, ваши проекты сокращаются и становятся более читабельными.

C ++ предоставляет вам все инструменты, необходимые для повторного использования методов вместо повторения кода. Хотя когда дело доходит до конструкторов, я не знаю, как их использовать.

Я не говорю о наследии или о том, как отправить сообщение отцу. Я говорю о повторном использовании конструктора самого класса.

Аналогия в JAVA выглядит примерно так:

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

У меня вопрос: есть ли синтаксис в C ++, который позволяет вам это делать?

Ответы [ 4 ]

11 голосов
/ 06 октября 2011

Другие уже ответили о C ++ 11, но для C ++ 03 есть обходной путь: использование базового класса с необходимым конструктором (ами).

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

Конечно, вы должны рассмотретьстоит ли шаблон для ваших целей.

10 голосов
/ 06 октября 2011

C ++ 11 добавил делегирование конструктора и наследование конструктора .

Для наследования конструкторов требуется объявление использования :

class Base { ... };

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

Чтобы делегировать, используйте ctor-initializer , но укажите любой конструктор в том же классе, вместо любых подобъектов (все базовые и подчиненные подобъекты будут инициализированы делегированным конструктором):

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

И идеальная пересылка также может пригодиться.

2 голосов
/ 06 октября 2011

Общепринятым для современных компиляторов является следующее:

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

Хотя в этом примере это может показаться чрезмерным уничтожением, это только из-за простоты примера. В реальных приложениях это на самом деле принесет выгоду с точки зрения сокращения повторяющегося кода.

1 голос
/ 06 октября 2011

OK C ++ 11 покрывает то, что вам нужно.

Но в вашем простом случае есть простое решение:

/* 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
...