2

I came across this on net, but wasn't convinced with variable number of arguments or using bridge pattern solution hence I am asking this over here. Thanks in advance.

class B
{
public:
B(args_1);
B(args_2);
// and many constructors with different arg lists
};

class D : public B
{
public:
D(args_1) : B(args_1) {}
D(args_2) : B(args_2) {}
// and many constructors with different signatures similarly implemented
// some additional stuff specific to D
};

Assume that the arg list for B's constructors are quite long and may be revised pretty often in the future, in which case D's constructors have to be recoded correspondingly. Duplicating the update by copy-and-paste will certainly work here. Can you propose a better way so that the update can be done in one place without copy-and-paste duplication?

options
  • 21
  • 2
  • Is inheritance (ergo polymorphic behavior) a requirement? – Andres Jaan Tack Mar 08 '11 at 15:53
  • 1
    If your complier supports any C++0x features, consider also http://stackoverflow.com/questions/3119929/forwarding-all-constructors-in-c0x – Steve Jessop Mar 08 '11 at 15:57
  • Let's say yes for sake of argument. However I am open to see non-polymorphic solution. As I mentioned it is just a hypothetical question i picked from net. – options Mar 08 '11 at 16:04
  • If you use B For defining an interface to several classes, you just cannot have a long list of parameters that changes pretty often. You have to decide on an interface first, and implement that later. Otherwise it **will** be a lot of work, not only updating the constructors, but also modify all the subclasses to presumably use the additional data in the base class. – Bo Persson Mar 08 '11 at 16:27

3 Answers3

2

Sure, use composition over inheritance:

class D{
public:
   D(auto_ptr<B> _obj) : mB(_obj){}
   //member functions which delegate to the calls of "B"
   //member functions specific to "D"
private:
   scoped_ptr<B> mB;
};
wheaties
  • 35,646
  • 15
  • 94
  • 131
  • 2
    +1 Inheritance is _only_ necessary when you want things to behave polymorphically. Compose unless you have to inherit. – Andres Jaan Tack Mar 08 '11 at 15:52
  • Consider `D(std::auto_ptr _obj)`, it's a sink (will take ownership). Also, I suspect the `const` is wrong. – MSalters Mar 08 '11 at 15:53
  • @Andres Jaan Tack exactly. @MSalters done and you're right about the const, should have been `B* const` instead of `const B*`. The former being a pointer that can change state of B, the later can't. – wheaties Mar 08 '11 at 15:57
  • I don't see ANY 'const' any more. Can you maybe leave the first version you send as it was, and the corrected version below it with an "EDIT:" before it? Then this const-discussion here can be understood and people (like me) can learn from it. Like this, it is just leaving a big "?" – AudioDroid Mar 08 '11 at 16:05
1

Let the compiler do the generating as and when needed:

template<typename T1> D(T1 t) : B(t1) { };
template<typename T1, typename T2> D(T1 t, T2 t2) : B(t1, t2) { };
MSalters
  • 173,980
  • 10
  • 155
  • 350
0

Create another class A that encapsulates the arguments and then pass on that to D.

class A
{
   int foo;
};

class A1: public A
{
   float bar;
};


class B
{
    B(const A& args);
};

class D: public B
{
    D(const A& args) : B(args)
    {
       // do more stuff
    }
};
florin
  • 13,986
  • 6
  • 46
  • 47
  • Wouldn't you still need to edit the constructor for both B and D everytime an arg was changed, assuming B and D cared about the change? – reuscam Mar 08 '11 at 16:04
  • @reuscam : No, but he might have to edit A and B instead. :-) – Bo Persson Mar 08 '11 at 16:23
  • @reuscam: I guess I don't understand your comment -- if D cared about the change and needed to react to it, then you have to 'pay' for it. My suggestion was to help the cases when D does not really care about what is sent to B. And obviously, if you want to change the arguments... you have to change the arguments - be it a list, or members in a structure. – florin Mar 08 '11 at 16:30