[英]Parametrized constructor in virtually inheriting abstract class
我有一個經典的虛擬繼承鑽石:
class A {
protected:
A(const char *x) { ... }
}
class B: public virtual A {
protected:
B(): A(NULL) { ... }
public:
virtual void foo() = 0;
}
class C: public virtual A {
protected:
C(): A(NULL) { ... }
public:
virtual void bar() = 0;
}
class D: public B, public C {
public:
D(const char *x): A(x) { ... }
void foo();
void bar();
}
我在B
和C
使用NULL,因為它們是抽象類,所以在它們的構造函數中永遠不會調用A
ctor。 有沒有更好的方法來做,否則在構造函數中指定NULL
或在A
聲明無參數構造函數? 我希望使用參數調用構造函數,因此只應在抽象類中允許A() {}
ctor。
您可以將A
更改為:
class A {
private:
A() {};
friend class B;
friend class C;
protected:
A(const char *x) { }
};
然后B(): A() {}
和C(): A() {}
可以工作,但D(const char*): A() {}
不會。 但這真的很尷尬。 我堅持你目前正在使用的NULL
。
不過,這確實是一個有趣的案例。 我認為沒有技術上的理由說明為什么你必須在B
和C
為A
指定一個構造函數,因為它們永遠不會被創建,無論是誰繼承它們都會初始化A
您可以在A(const char*)
指定默認參數 A(const char*)
class A {
protected:
A(const char *x = 0) { ... }
^^^^
};
但是,這也將允許D
避免A()
。
我正在關閉這個,因為嚴格的答案可能不存在。 IMO最好的解決方法是
struct AbstractPlaceholder {
AbstractPlaceholder() {
assert(false);
}
};
class A {
protected:
A(const AbstractPlaceholder &ap) {}
A(const char *x) { ... }
};
你的方法的變化將是
class A {
protected:
A(const char *x = NULL) {
assert(x && "A mustn't be default constructed!");
}
};
從而添加更有意義的診斷。
但是,您可能希望明確允許x
為NULL
(作為通過C
的合法構造),然后您可以使用Maybe
類型。
template <typename T> class Maybe {
T const t; // must be default constructible!
bool const invalid;
public:
Maybe() : t(), invalid(true) {}
Maybe(T t) : t(t), invalid(false) {}
bool nothing() const {
return invalid;
}
T just() const {
assert(!invalid);
return t;
}
};
然后你可以改變你的構造函數
A::A(Maybe<const char*> mx) {
// either
assert(!mx.nothing());
// or
mx.just();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.