我想允许以下行为:
struct SignalBase {};
struct Signal1 : public SignalBase
{ using SignalBase::SignalBase; };
struct Signal2 : public SignalBase
{ using SignalBase::SignalBase; };
int main()
{
Signal1 s1;
Signal2 s2(s1);
}
当然,这不起作用,因为SignalBase
没有构造函数接收派生类型,并且复制构造函数不会继承using
子句。
我试图用SignalBase中的模板构造函数来解决这个问题:
// External function:
template<typename Derived, typename Base>
constexpr bool isDerived()
{
return std::is_base_of<Base, Derived>::value and
!std::is_same<Base, Derived>::value;
}
struct SignalBase
{
template<typename Signal>
SignalBase(Signal const& s) // (1)
{ static_assert(isDerived<Signal, SignalBase>(), "Invalid copying"); }
};
由于构造函数(1)不能与复制构造函数混淆(如果我没错,模板构造函数不被认为是复制构造函数,因为非模板复制构造函数优先于模板构造函数,如果它们具有相同的签名作为实例化后的拷贝构造函数。)
因此,构造函数(1)应该在派生类中继承:
// struct Signal1 inherits:
template<typename Signal>
Signal1(Signal const& s) // (2)
{ static_assert(isDerived<Signal, SignalBase>(), "Invalid copying"); }
// struct Signal2 inherits:
template<typename Signal>
Signal2(Signal const& s) // (3)
{ static_assert(isDerived<Signal, SignalBase>(), "Invalid copying"); }
和以下一行:
Signal2 s2(s1);
应该使用Signal
= Signal1
实例化(3),这是一个Signal的派生类,并且不会因static_assert
子句而导致错误。
但是这并没有发生,因为编译错误表明没有找到Signal1
到Signal2
的转换。
为什么基础构造函数没有被正确继承,以及在派生类中真正继承的是什么?
注意:在我的实际代码中(为简单起见未在此示例中显示),派生信号是模板,而转换运算符仅适用于显式转换(使用(Type)object
运算符) ,在我在函数之间发送对象的地方使行太长。这就是为什么我想通过构造函数来寻找方法来实现它。
注意2 :请关注C ++问题(实际上是继承?)而不是其他OOP注意事项(例如,从基础clases构造派生对象是否有意义?) ,因为这是我真实代码的一个非常简化的例子。
答案 0 :(得分:2)
通过添加第二层基类,可以在没有模板的情况下完成:
class SignalBase
{
/* all the members */
};
struct CopyableSignalBase : SignalBase
{
// not actually a copy constructor, so using will pick it up
CopyableSignalBase(const SignalBase& src) : SignalBase(src) {}
// make all other (not copy and not default) constructors available too
using SignalBase::SignalBase;
// since using doesn't introduce default constructor, provide it
// if and only if SignalBase had one
CopyableSignalBase() = default;
};
struct Signal1 : public CopyableSignalBase
{ using CopyableSignalBase::CopyableSignalBase; };
struct Signal2 : public CopyableSignalBase
{ using CopyableSignalBase::CopyableSignalBase; };
请注意,根据this feature matrix,在VS14之前,Visual Studio根本无法处理继承构造函数。但是没有构造函数继承,整个问题就毫无意义。