从构造函数体中调用超类构造函数

时间:2018-01-18 11:17:22

标签: c++ oop inheritance

我想创建一个类构造函数,它只在某些条件下调用它的超类构造函数。我目前的实现如下所示。

class MyClass : public OtherClass
{
public:
    template<typename... Args>
    MyClass(bool condition, Args&&... args)
    {
        if(condition)
        {
            *(OtherClass*)this = OtherClass(args...);
        }
        else
        {
            //  Unrelated stuff
        }
    }
};

我不能在这里使用MyClass(...) : OtherClass(...) {}语法,因为每次都不应该调用超类的构造函数。

有没有办法直接调用超类构造函数而不是调用移动构造函数(如我的例子所示)。

4 个答案:

答案 0 :(得分:2)

您可以为基类和派生类创建2个不同的构造函数 派生类的构造函数调用基类的相应构造函数 派生类中的静态方法基于传递的参数创建实例 像这样:

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

答案 1 :(得分:1)

解决方案是不在构造函数中执行此操作,而是在辅助函数中执行此操作。例如:

class BaseClass {
    BaseClass() {}
    BaseClass(int x) {setX(x);}
    void setX(int x) {
        //thing
    }
}

class Derived : BaseClass {
    Derived(int x) {
        if (x>10) setX(x);
    }
}

答案 2 :(得分:0)

您可以通过以下方式重载构造函数以实现标记分派

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() {}
};

答案 3 :(得分:0)

Robert Kock的回答并不完全正确。他从派生类构造函数的初始化列表中调用Base类(超类)构造函数但没有条件。但根据你的问题can we call a base class constructor based on a CONDITION from the BODY of derived class constructor?。答案是否定我们做不到。根据面向对象的原则,Base类构造函数必须首先调用和初始化。在Robert Kock的上述答案中,在控制进入正文并且没有任何条件之前,从驱动类构造函数的初始化列表中调用基类构造函数。在初始化列表中,您甚至无法提出任何条件。因此,无法调用基于类的构造函数来从派生类构造函数的主体进行调用。这就是我们在类中引入一个名为init()的方法的原因。现在,以下示例可以完全满足您的要求。在这个示例中,您必须在基类中添加一个默认构造函数,以便此默认构造函数首先调用,但在该默认构造函数中,您不会执行任何操作。

现在看下面的例子: -

#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;
}