3

Suppose I have a large class with a lot of functionality and a relatively large interface. Particularly, there are many constructors for convenient instantiation. From this class, several classes could be derived with some slightly extended interface and/or customized virtual functions.

The problem: I will have to copy all the constructors into the derived classes which would mean a lot of code duplication. Even worse: The constructors slightly depend on the derived class, which I would solve by a virtual call, but this does not work in a constructor.

What's a good approach to tackle this problem?

EDIT: I know that I can delegate constructors Derived(arguments) : Base(arguments) {} but I'd still need to copy parts of the constructor which I try to avoid.

Michael
  • 7,407
  • 8
  • 41
  • 84

4 Answers4

3

Use using declarations to make the constructors of the base class aviable on the derived one:

class Base
{
public:
    Base( int , int , int );
};

class Derived : public Base
{
public:
    using Base::Base; //Automatically adds all the base constructors
};

EDIT: Here is a running example.

Manu343726
  • 13,969
  • 4
  • 40
  • 75
  • Note that this is a C++11 feature called [*constructor inheritance*](http://stackoverflow.com/questions/9979194/what-is-constructor-inheritance) – Manu343726 Jul 15 '14 at 10:54
  • Leads to a compile error: `error #1140: a using-declaration may not name a constructor or destructor`. Although I use C++11 features in other parts of the code with compile flag -std=c++0x (Intel). – Michael Jul 15 '14 at 10:56
  • @Michael some compilers have not implemented constructor inheritance yet. What compiler are you using? – Manu343726 Jul 15 '14 at 10:57
  • It's icpc-2013. Many C++ 11 features are implemented and I can use them, but this does not seem to work. – Michael Jul 15 '14 at 11:01
  • In Ubuntu with `cc` it works, with a warning `warning: inheriting constructors only available with -std=c++11 or -std=gnu++11 [enabled by default]`. – Alexander Gelbukh Jul 15 '14 at 11:03
  • It turns out that no Intel compiler supports this feature. – Michael Jul 15 '14 at 11:06
  • 1
    @Michael as [this table](https://software.intel.com/en-us/articles/c0x-features-supported-by-intel-c-compiler) shows, the icpc does not support inheriting constructors yet. Also both you and Alexander should use `-std=c++11` instead of `-std=c++0x` – Manu343726 Jul 15 '14 at 11:06
2

I do not know exactly if it works for your problem, but you might think about making some kind of 'initialization' object where you handle the properties of the object you want to create. This will have a lot of constructors.

Then you pass this object to the 'real' class where the properties are used to create the actual object.

Michel Keijzers
  • 15,025
  • 28
  • 93
  • 119
1

If C++ 11 extensions can be used, then the other answer that recommends using is a perfect answer.

If not, then the only way is:

class x:  public y
{
    // modified constructors:

    x (int a) : y (1, 2, a + 3) { your code if any; }
    x (int a, int b) : y (b, a) { your code if any; }

    // delegated constructors: alas, repeated for all constructors of y

    x (int c, float d) : y (c, d) { /* no code*/ }
    x (float e, int f) : y (e, f) { /* no code*/ }
}

The latter part is not really code duplication because you only duplicate interface but no code.

Alexander Gelbukh
  • 2,104
  • 17
  • 29
  • That would of course be a solution, but still with the mentioned drawback of copying a lot of constructors at least partially. – Michael Jul 15 '14 at 10:37
  • I fear there is no other way. If you just call a constructor of `y`, you will not get `x`. But to call `x`, you need a corresponding constructor of `x`, even if `y` already has it. Sorry, a long row of `x (some args) : y (same args) {}`. – Alexander Gelbukh Jul 15 '14 at 10:41
  • I also think that the language does not provide a direct way to do it. Some architectural change will probably be necessary. – Michael Jul 15 '14 at 10:42
  • So does this answer your question? – Alexander Gelbukh Jul 15 '14 at 10:54
0

Do the initializations applicable in respective classes. For example, say A is superclass and B is a subclass, so you may use,

B::B(...arguments...): A(...arguments that you would like to pass to superclass constructor)
{
}
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69