对基构造函数的条件调用

Conditional call to base constructor

本文关键字:条件 调用 构造函数      更新时间:2023-10-16

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

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

以及基类的派生类。我想做的是在派生类的构造函数中选择哪个构造函数调用,而不是在初始值设定项列表中。像这样:

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

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

谢谢

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

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

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

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

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派生,则可以将Base的实例视为成员(std::unique_ptrstd::aligned_storage(,您可以随意初始化。

基于他回答中的@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);

}