3

I have class D inherited from B:

struct D: public B {
    D(int b1, int p);
    D(int b1, int b2, int p);
    int p1;
    float p2;
    double p3;
    std::string p4;
};

Contructors code is the same except base class intilization:

 D::D(int b1, int p): B(b1)
 , p1(p)
 , p2(SomeFunc())
 , p3(SomeOtherFunc() - 42)
 , p4("abc")
 {}

 D::D(int b1, int b2, int p): B(b1, b2)
 , p1(p)
 , p2(SomeFunc())
 , p3(SomeOtherFunc() - 42)
 , p4("abc")
 {}

The question: is there any way to make the code more compact and less "copy-pasted"?

Nick
  • 3,205
  • 9
  • 57
  • 108

2 Answers2

5

Use a delegating constructor.

// Assuming default value of b2 is 0.
D::D(int b1, int p): D(b1, 0, p) {}

 D::D(int b1, int b2, int p): B(b1, b2)
 , p1(p)
 , p2(SomeFunc())
 , p3(SomeOtherFunc() - 42)
 , p4("abc")
 {}

See http://www.stroustrup.com/C++11FAQ.html#delegating-ctor for additional information on delegating constructors.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Generally speaking, calling `B(b1, 0)` is not the same as calling `B(b1)`. So I am afraid that what you propose does not produce the same effect as my original code. – Nick Mar 14 '19 at 18:42
  • @Nick, agree. If default value of `b2` is not documented, then this will be a problem. – R Sahu Mar 14 '19 at 18:44
3

You can use in class member initializers to specify default values for class members.

struct D: public B {
    D(int b1, int p);
    D(int b1, int b2, int p);
    int p1;
    float p2;
    double p3;
    std::string p4;
};

can be changed to

struct D: public B {
    D(int b1, int p);
    D(int b1, int b2, int p);
    int p1;
    float p2{SomeFunc()};
    double p3{SomeOtherFunc() - 42};
    std::string p4{"abc"};
};

and then you do not you do not need to list those members in the member initialization list if you are fine having the default value. That makes the constructors look like

D::D(int b1, int p): B(b1), p1(p) {}

D::D(int b1, int b2, int p): B(b1, b2), p1(p) {}
NathanOliver
  • 171,901
  • 28
  • 288
  • 402