2

I've a class with some overloaded constructor and no default constructor. The overloaded constructor essentially do the same things but differ on the type of params provided. Let's say I've a class as follows -

struct info {
  int one;    // must be filled
  int two;    // can be empty
  int three;  // can be empty
}

class A {
    int a;
    double b;
    float c;
    info I;

  public:

    A(a,b,c,one) :
      a(a),
      b(b),
      c(c)
    {
        // some processing
        I.one = one;
        // some other processing
        ....
    }

    A(a,b,c,i) :
      a(a),
      b(b),
      c(c),
      I(i)
    {
        // some processing
        // some other processing
        ....
    }

}

The processing and some processing part is repeating and is slightly dependent on certain paths which are frequently edited, forcing us to do same and same changes to both places.

Can this be reduced to same constructor in some way? I was hoping to do something with constructor delegation, but wasn't able to think of a clever way to do this :/

hg_git
  • 2,884
  • 6
  • 24
  • 43
  • please explain the downvotes.. I would gladly improve my question :) – hg_git Sep 02 '16 at 16:32
  • I don't know, but it could be due to your failure to specify the types of the arguments in your constructors (i.e. `A(int a, int b, ...`), or just the fact that you have a lot of code....? The question seems perfectly reasonable to me. – Kyle Strand Sep 02 '16 at 23:58

2 Answers2

6

Can this be reduced to same constructor in some way?

Yes. In C++11 there are delegating constructor.

For example:

class Foo {
public: 
  Foo(char x, int y) {}
  Foo(int y) : Foo('a', y) {} // Foo(int) delegates to Foo(char,int)
};

EDIT:

As requested, take your example:

class A {
 private:
  A (int _a, double _b, float _c) : a(_a),
                                    b(_b),
                                    c(_c) {
    // This constructor does a lots of stuff...
  }

 public:
  A (int _a, double _b, float _c, int _one) : A(_a, _b, _c) {
    I.one = _one
    // This constructor does nothing
    // Because A(_a, _b, _c) already does everything
  }

  A (int _a, double _b, float _c, info _info) : A(_a, _b, _c) {
    I = _info;
    // This constructor does nothing
    // Because A(_a, _b, _c) already does everything
  }
};
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
BiagioF
  • 9,368
  • 2
  • 26
  • 50
  • could you do this taking my example? Since I've a tricky condition where 1 overload is of the struct itself while another version is of its member. – hg_git Sep 02 '16 at 16:31
  • 1
    @hg_git: you can create a private constructor that does common part and use it from your public constructors – Andriy Tylychko Sep 02 '16 at 16:35
  • Is this a valid syntax `I.one(one)` ? – Slava Sep 02 '16 at 16:40
  • I do not believe so. It should only work for members, not members of members. – NathanOliver Sep 02 '16 at 16:41
  • `A (int _a, double _b, float _c, info _info) : A(_a, _b, _c), I(_info)` is not valid either. – NathanOliver Sep 02 '16 at 16:43
  • @NathanOliver Ups... too fast. Well I fixed it. – BiagioF Sep 02 '16 at 16:48
  • Thankyou for fixing my example, I couldn't share the original code and hence had to type this out. Stupid brain made some stupid types :/ – hg_git Sep 02 '16 at 16:54
  • Also it is acceptable to create private ctors? I mean I know it is perfectly valid syntax, but is it considered a bad practice or just fine? – hg_git Sep 02 '16 at 16:55
  • @hg_git I think in this case should be fine. In general it should not be a problem, but obviously it depends on the specific case. – BiagioF Sep 02 '16 at 16:57
2

Just create a proper ctor for info:

struct info {
  int one;    // must be filled
  int two;    // can be empty
  int three;  // can be empty

  info( int lone, int ltwo = 0, int lthree = 0 ) :
      one( lone ), two( ltwo ), three( lthree ) {}
};

then you only need one ctor for class A that accepts info, or you can express that explicitly:

 A(int la, double lb, double lc, int one) :
    A( la, lb, lc, info( one ) )
 {
 }
Slava
  • 43,454
  • 1
  • 47
  • 90
  • 1
    This is only viable if `info` can be a non-aggregate. If it needs to be an aggregate you cannot supply a constructor. – NathanOliver Sep 02 '16 at 16:44
  • @NathanOliver I'm feeling stupid here but could you explain what you mean when saying - `If it needs to be an aggregate`.. what is meant by aggregate.. – hg_git Sep 02 '16 at 16:51
  • 1
    @hg_git see: http://stackoverflow.com/questions/4178175/what-are-aggregates-and-pods-and-how-why-are-they-special – NathanOliver Sep 02 '16 at 16:54