[英]Parametrized constructor in virtually inheriting abstract class
I have a classical virtual inheritance diamond: 我有一个经典的虚拟继承钻石:
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();
}
I use NULL in B
and C
because as they're abstract classes, the A
ctor will never be called in their constructurs. 我在B
和C
使用NULL,因为它们是抽象类,所以在它们的构造函数中永远不会调用A
ctor。 Is there a nicer way to do it, otherwise than specify NULL
in the constructor or declare parameterless constructor in A
? 有没有更好的方法来做,否则在构造函数中指定NULL
或在A
声明无参数构造函数? I want the constructor to be called with a parameter, therefore the A() {}
ctor should be allowed only in abstract classes. 我希望使用参数调用构造函数,因此只应在抽象类中允许A() {}
ctor。
You can change A
to: 您可以将A
更改为:
class A {
private:
A() {};
friend class B;
friend class C;
protected:
A(const char *x) { }
};
And then B(): A() {}
and C(): A() {}
would work, yet D(const char*): A() {}
won't. 然后B(): A() {}
和C(): A() {}
可以工作,但D(const char*): A() {}
不会。 But this is really awkward. 但这真的很尴尬。 I'd stick with the NULL
you're using at the moment. 我坚持你目前正在使用的NULL
。
This is indeed an interesting case, though. 不过,这确实是一个有趣的案例。 I could think of no technical reason why you'd have to specify a constructor for A
in B
and C
given they'll never be created, and whoever inherits them is going to initialize A
anyway. 我认为没有技术上的理由说明为什么你必须在B
和C
为A
指定一个构造函数,因为它们永远不会被创建,无论是谁继承它们都会初始化A
You can specify default argument in A(const char*)
您可以在A(const char*)
指定默认参数 A(const char*)
class A {
protected:
A(const char *x = 0) { ... }
^^^^
};
However, this will also allow D
to avoid A()
. 但是,这也将允许D
避免A()
。
I am closing this as the rigth answer probably does not exist. 我正在关闭这个,因为严格的答案可能不存在。 IMO the best workaround is the IMO最好的解决方法是
struct AbstractPlaceholder {
AbstractPlaceholder() {
assert(false);
}
};
class A {
protected:
A(const AbstractPlaceholder &ap) {}
A(const char *x) { ... }
};
A variation of your approach would be 你的方法的变化将是
class A {
protected:
A(const char *x = NULL) {
assert(x && "A mustn't be default constructed!");
}
};
Thereby adding a more meaningful diagnostic. 从而添加更有意义的诊断。
However, you may want to explicitly allow x
to be NULL
(as a legal construction via C
), then you could use a Maybe
type. 但是,您可能希望明确允许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;
}
};
Then you can change your constructor to 然后你可以改变你的构造函数
A::A(Maybe<const char*> mx) {
// either
assert(!mx.nothing());
// or
mx.just();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.