目前,我有一个基于两个不同构造函数的基类:
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);
}
}
是否可以这样做?或者因为基类是在派生类之前初始化的,调用基本构造函数的唯一方法是在初始化列表中?
由于
答案 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
的实例可以作为成员(Base
或std::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);
}