Reputation: 2583
I want to create a class constructor which will call it's superclass constructor only on certain condition. My current implementation of this is shown below.
class MyClass : public OtherClass
{
public:
template<typename... Args>
MyClass(bool condition, Args&&... args)
{
if(condition)
{
*(OtherClass*)this = OtherClass(args...);
}
else
{
// Unrelated stuff
}
}
};
I can't use MyClass(...) : OtherClass(...) {}
syntax here because superclass's constructor should not be called every time.
Is there any way to call superclass constructor directly instead of calling move constructor (as shown in my example).
Upvotes: 0
Views: 3549
Reputation: 5591
Above answer from Robert Kock is not perfectly correct. He is calling Base class (supper class) constructor from initialization list of derived class constructor but without a condition. But as per your question can we call a base class constructor based on a CONDITION from the BODY of derived class constructor?
. The answer is NO we can not. As per object oriented principle A Base class constructor must call and initialized first. In the above answer from Robert Kock, base class constructor is called from the initialization list of drive class constructor before control enter inside the body and without any condition. In the initialization list you can not even put any condition. So it is not possible to call a based class constructor to call from the body of a derive class constructor. That is the reason for this kind of requirement we introduce one more method called init() in a class. Now the below example can full fill your requirement. Here in this example you have to add one default constructor in your base class, so that this default constructor call first but in that default constructor you are not going to do anything.
Now see the below example:-
#include<iostream>
class B
{
private:
int x;
int y;
public:
B(){std::cout<<"I am B's default constructor"<<std::endl;}//Default constructor not doing anything
void init(int x)
{
std::cout<<"Based init with param x"<<std::endl;
this->x = x; //this method initializing only one member
y = 0;// just initialized with default value 0
}
void init(int x,int y)
{
std::cout<<"Based init with param x and y"<<std::endl;
this->x = x; // here we initializing all the members
this->y = y;
}
void print()
{
std::cout<<"x ="<<x<<std::endl;
std::cout<<"y ="<<y<<std::endl;
}
};
class D : public B
{
public:
D(int i)
{
std::cout<<"I am D's constructor"<<std::endl;
if( i == 1 )
B::init(3);
else
B::init(4, 5);
}
};
int main()
{
std::cout<<"First Example"<<std::endl;
D *d = new D(1);
d->print();
std::cout<<"Now second Example"<<std::endl;
D *d1 = new D(2);
d1->print();
return 0;
}
Upvotes: 0
Reputation: 24738
You could overload the constructor in the following way to implement tag dispatching:
struct PassArgs {};
struct DoNotPassArgs {};
class MyClass: public OtherClass {
public:
template<typename... Args>
MyClass(PassArgs, Args&&... args) : OtherClass(args...) {}
template<typename... Args>
MyClass(DoNotPassArgs, Args&&...) : OtherClass() {}
};
Upvotes: 0
Reputation: 6983
A solution is to not do this in the constructor, but in a helper function. For example:
class BaseClass {
BaseClass() {}
BaseClass(int x) {setX(x);}
void setX(int x) {
//thing
}
}
class Derived : BaseClass {
Derived(int x) {
if (x>10) setX(x);
}
}
Upvotes: 1
Reputation: 6008
You could create 2 different constructors for both the base- and the derived class.
The constructor of the derived class calls the appropriate constructor of the base class.
A static method within the derived class creates an instance based on the passed arguments.
Something like this:
class OtherClass
{
public:
OtherClass()
{
...
}
OtherClass(Args&... args)
{
...
}
} // class OtherClass
class MyClass: public OtherClass
{
private:
MyClass(): OtherClass()
{
...
}
MyClass(Args&... args): OtherClass(args)
{
...
}
public:
static MyClass* createInstance(bool condition,
Args&&... args)
{
if (condition)
return (new MyClass());
else
return (new MyClass(args));
}
} // class MyClass
Upvotes: 2