Change constructor parameter values ​​before calling the base class constructor

I have the following class hierarchy:

class Base { // This class cannot be modified public: Base(int a, int b, int c) { if ( a == 100 && b == 200 && c < 100 ) // whatever condition throw "Error!"; } }; class Derived : public Base { // this class can be modified public: Derived(int a, int b, int c) : Base(a, b, c) {} }; 

The Derived class is used in many places in the code, so it cannot be replaced with any factory function.

Now the question is, is there any construction that would allow me to correct the values ​​of a, b, c before calling the Base constructor?

I know that I can use functions such as:

  Derived(int a, int b, int c) : Base(FixA(a), FixB(b), FixC(c)) {} int FixA(int a) { /*fix a value*/ return a; } int FixB(int b) { /*fix b value*/ return b; } int FixC(int c) { /*fix c value*/ return c; } 

but it will not allow me to set the correct values ​​in the case when the values ​​of bc depend as in the above c-tor example of the base class.

I thought to expand this to:

  Derived(int a, int b, int c) : Base(FixA(a,b,c), FixB(a,b,c), FixC(a,b,c)) {} int FixA(int a, int& b, int& c) { /*fix abc values*/ return a; } int FixB(int& a, int b, int& c) { /*fix abc values*/ return b; } int FixC(int& a, int& b, int c) { /*fix abc values*/ return c; } 

I suppose there should also be some kind of flag indicating that the correction has already been completed. I am not sure if this is really correct with C ++.

I know that the best solution is actually throwing an exception.

+4
source share
3 answers

Consider placing a class between Derived and Base :

 class Derived: public UnpackToBase { public: Derived(int a, int b, int c): UnpackToBase(FixParameters(a, b, c)) class UnpackToBase: public Base { public: UnpackToBase(FixParameters params): Base(params.a, params.b, params.c) struct FixParameters { int a, b, c; FixParameters(int a, int b, int c): a(a), b(b), c(c) { // do stuff } 

In C ++ 11, you can use the Derived delegation constructor:

 class Derived: public Base { public: Derived(int a, int b, int c): Derived(FixParameters(a, b, c)) { } Derived(FixParameters params): Base(params.a, params.b, params.c) { } 
+8
source

You can use the singleton pattern to solve this problem. See code below. Here, the order of initialization of the construction initialization list does not matter. However, I doubt if it can be called elegant.

 class Base { // This class cannot be modified public: Base(int a, int b, int c) { if ( a == 100 && b == 200 && c < 100 ) // whatever condition throw "Error!"; } }; class Validator { public: static Validator& instance(int a_in, int b_in, int c_in) { static Validator v(a_in,b_in,c_in); return v; } int& a(){ return m_a;} int& b(){ return m_b;} int& c(){ return m_c;} private: Validator(int a_in, int b_in, int c_in) : m_a(a_in), m_b(b_in), m_c(c_in) { // perform validation and modify the members // Example validation if(m_a > 0 && m_b > 0) { m_c = 0; } } int m_a; int m_b; int m_c; }; class Derived : public Base { // this class can be modified public: Derived(int a, int b, int c) : Base(Validator::instance(a, b, c).a(), Validator::instance(a, b, c).b(), Validator::instance(a, b, c).c()) {} }; int _tmain(int argc, _TCHAR* argv[]) { Derived d(1,2,3); return 0; } 
+1
source

It looks like you have no hacking problem, you need to do something weird, so why not use good ol macros ..

 #define FIX_ME(x) //do something Derived(int a, int b, int c) : Base(FIX_ME(a), FIX_ME(b), FIX_ME(c)) {} 
0
source

All Articles