我有一个经典的虚拟继承钻石:
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。
答案 0 :(得分:0)
您可以将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
。
但这确实是一个有趣的案例。我认为没有任何技术原因可以让你 在A
和B
中指定C
的构造函数,因为它们永远不会被创建,并且无论如何,继承它们的人都会初始化A
。
答案 1 :(得分:0)
您可以在A(const char*)
class A {
protected:
A(const char *x = 0) { ... }
^^^^
};
但是,这也允许D
避免A()
。
答案 2 :(得分:0)
我正在关闭这个,因为正确的答案可能不存在。
是最好的解决方法struct AbstractPlaceholder {
AbstractPlaceholder() {
assert(false);
}
};
class A {
protected:
A(const AbstractPlaceholder &ap) {}
A(const char *x) { ... }
};
答案 3 :(得分:0)
您的方法的变体将是
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();
}