条件调用基础构造函数

时间:2018-06-12 14:56:06

标签: c++ inheritance constructor

目前,我有一个基于两个不同构造函数的基类:

class Base {
public:
   Base(std::string filname){...}
   Base(int a, int b) {...}
};

和Base类的派生类。我想要做的是选择派生类的构造函数内部的构造函数调用,而不是在初始化程序列表中。像这样:

class Derived : public Base {
public:
    Derived() {
        if( /* exists("myFile") */ )
            this->Base("myFile");
        else
            this->Base(1,2);
    }
}

是否可以这样做?或者因为基类是在派生类之前初始化的,调用基本构造函数的唯一方法是在初始化列表中?

由于

3 个答案:

答案 0 :(得分:7)

调用哪个基础构造函数的选择发生在函数体之前,并且无法在运行时更改它。但是,您可能会接近。如果基类也有移动构造函数,或者你可以添加一个,你可以使用:

class Derived : public Base {
public:
    Derived()
        : Base{ exists("myFile") ? Base{"myFile"} : Base{1, 2} } {
    }
}

这将调用exists("myFile");如果返回true,它将使用第一个构造函数构造一个临时Base,如果它返回false,它将使用第二个构造函数构造一个临时Base。无论哪种方式,它都将使用此临时构造实际基础子对象。

答案 1 :(得分:1)

您可以通过引入工厂函数来模拟它:

interface IFoo {
  type: 'foo';
  foo: string;
}

interface IBar {
  type: 'bar';
  bar: string;
}

type FooBar = IFoo | IBar;

type Xxx<T extends FooBar> = T extends IFoo ? { a: string } : { b: string };

class Getter<T extends FooBar> {
  private data: T;
  private xxx: Xxx<T>;

  constructor(data: T, xxx: Xxx<T>) {
    this.data = data;
    this.xxx = xxx;
  }

  public getMe(): string {
    const data: FooBar = this.data;
    const { xxx } = this;
    // Property 'a' does not exist on type 'Xxx<T>'.
    // Property 'b' does not exist on type 'Xxx<T>'.
    return data.type === 'foo' ? xxx.a : xxx.b;
  }
}

或者,如果不需要从class Base { public: Base(std::string filname); Base(int a, int b); }; class Derived : public Base { Derived(std::string filname) : Base(filname) {} Derived(int a, int b) : Base(a, b) {} public: static Derived create() { if( /* exists("myFile") */ ) return Derived("myFile"); else return Derived(1,2); } }; int main(){ auto d = Derived::create(); } 派生,Base的实例可以作为成员(Basestd::unique_ptr)保留,但您可以初始化请。

答案 2 :(得分:1)

基于@DanielH 在他的回答中的评论,我开发了一个替代解决方案,它也适用于 C++11 中的抽象基类:

#include <iostream>


struct Base {

    Base(int x) {
      std::cout << "Base x = " << x << std::endl;
    }
    
    Base() {
      std::cout << "Base default" << std::endl;
    }

    virtual void foo() = 0;

};


struct Derived : Base {

    struct TagA {};
    struct TagB {};

    Derived(bool condition)
    : Derived(condition ? Derived{TagA()} : Derived{TagB()})
    {}
    
    void foo() override {}
    
  private:
  
    Derived(TagA dummy)
    : Base(42)
    {
      std::cout << "Derived A dummy" << std::endl;
    }
    Derived(TagB dummy)
    {
      std::cout << "Derived B dummy" << std::endl;
    }



};


int main() {

    std::cout << "Construct Derived with false" << std::endl; 
    Derived x(false);

    std::cout << "Construct Derived with true" << std::endl; 
    Derived y(true);
  

}