【发布时间】:2017-08-27 00:28:44
【问题描述】:
我有一个模板基类,它有一个构造函数,用于从该类的任何其他模板实例进行转换,如下所示:
template <class T>
class FooBase
{
public:
FooBase()
{
}
template <class U>
FooBase(const FooBase<U>& other)
{
std::cout << "FooBase<U>" << std::endl;
}
};
注意没有定义复制构造函数。
然后我有一个派生模板类,它确实有一个复制构造函数,以及用于转换的构造函数:
template <class T>
class Foo : public FooBase<T>
{
public:
Foo()
{
}
Foo(const Foo& other) :
FooBase<T>(other)
{
}
template <class U>
Foo(const Foo<U>& other) :
FooBase<T>(other)
{
}
};
因为FooBase 没有复制构造函数,这导致FooBase<T>(other) 调用编译器生成的复制构造函数。这意味着如果我运行这个:
int main()
{
Foo<int> a;
Foo<int> b(a);
return 0;
}
输出是nothing,应该是FooBase<U>。
当然,我可以尝试通过在FooBase 中创建一个复制构造函数并使用delegating constructors 来解决这个问题:
FooBase(const FooBase& other)
: FooBase<T>(other)
{
}
但不幸的是,这不起作用,它会导致递归调用,正如编译器有用地指出的那样:
warning C4717: 'FooBase<int>::FooBase<int>': recursive on all control paths, function will cause runtime stack overflow
因此,唯一的解决方案是将逻辑复制到两个构造函数中。
是否有任何不涉及代码重复或单独的初始化函数的解决方法?
【问题讨论】:
-
那是因为
FooBase<T>实际上命名了当前类,因此委托返回到复制构造函数,而不是构造函数模板。 -
你可以直接使用模板类型名而不是 FooBase,但是你会在this problem
标签: c++ templates inheritance constructor