类来获取基的任何子类 我认为这是一个简单的问题,但是我的C++知识也是如此。
我有一个班叫学习者:类来获取基的任何子类 我认为这是一个简单的问题,但是我的C++知识也是如此。,c++,templates,C++,Templates,我有一个班叫学习者: template <class T> class Learner { T* _someRef; (...) } 模板 课堂学习者{ T*_someRef; (...) } 以及对象从中继承的基类 我的想法是让学习者接受任何子类基础的对象,例如Base1、Base2等。我可以用C++ 11的Type特性来断言这个类型。问题是,我需要为每个基本扩展提供模板专门化,例如: template Learner<T>::Learner(...) { //
template <class T>
class Learner {
T* _someRef;
(...)
}
模板
课堂学习者{
T*_someRef;
(...)
}
以及对象从中继承的基类
我的想法是让学习者接受任何子类基础的对象,例如Base1、Base2等。我可以用C++ 11的Type特性来断言这个类型。问题是,我需要为每个基本扩展提供模板专门化,例如:
template Learner<T>::Learner(...) { //implementation };
// However I am required to declare template-specifications for each Base
// derived type, else I'll get compiler errors. This seems useless as
// the generic-inplementation will still be called, but requires me to
// specify a declaration for each Base extension.What if I have n Base
// extensions, makes no sense to do this for 50 Base extensions.
template Learner<Base1>::Learner(...);
template Learner<Base2>::Learner(...);
模板学习者::学习者(…){//implementation};
//但是,我需要声明每个基地的模板规格
//派生类型,否则我将得到编译器错误。这似乎毫无用处
//泛型实现仍将被调用,但需要我
//为每个基扩展指定一个声明。如果我有n个基扩展呢
//扩展,对于50个基本扩展这样做没有意义。
模板学习者::学习者(…);
模板学习者::学习者(…);
这在一定程度上违背了我试图实现的目的,因为每个类的操作都是相同的,因为它们都实现了Base的虚拟函数。我怎样才能做到这一点?制作n模板规范似乎不正确。。。它适用于少量扩展,但如果难以处理,则适用于较大数量的扩展。如果我理解您的问题,我认为您需要的是
static\u assert
:
template<typename T>
struct Foo {
static_assert(is_base_of<Base, T>::value, "T must inherit from Base");
};
模板
结构Foo{
静态_断言(是_base_of::value,“T必须从base继承”);
};
对于C++11,您需要提供一条消息:
此外,如果需要,还可以使用type_traits进行编译时检查:
模板
课堂学习者
{
静态断言(std::is_base_v);
T*_someRef;
// ...
};
除了静态断言(…)
为了帮助解决虚拟继承的问题,您可以在派生类中使用关键字override
,如下所示:
class Base {
public:
virtual doSomething() = 0; // purely virtual
};
class DerivedA : public Base {
public:
virtual doSomething() override;
};
class DerivedB : public Base {
public:
virtual doSomething() override;
};
这样有助于避免任何歧义
编辑
我添加此部分是为了看看它是否有助于OP:
template <class T>
class Learner {
T* _someRef;
public:
Learner() { _someRef = new T(); }
~Learner() {
if ( _someRef != nullptr ) {
delete _someRef;
_someRef = nullptr;
}
}
void caller() {
_someRef->doSomething();
}
};
class Base {
public:
virtual void doSomething() = 0;
};
class D1 : public Base {
public:
virtual void doSomething() override {
std::cout << "D1's doSomething was called" << std::endl;
}
};
class D2 : public Base {
public:
virtual void doSomething() override {
std::cout << "D2's doSomething was called" << std::endl;
}
};
int main() {
Learner<D1> ld1;
Learner<D2> ld2;
ld1.caller();
ld2.caller();
_getch();
return 0;
}
如果我们尝试这样做:
{
Learner<D3> ld3; // compiler error
Learner<D3> ld3( 5 ); // compiler error
Learner<D3> ld3( D3( 5 ) ); // compiler error
D3 d3(5);
Learnder<D3> ld3( d3 ); // compiler error
}
我希望这能帮助您理解使用类模板进行专门化和/或部分专门化的原因。对于默认的可构造完整类型,您不需要专门化,但是对于非默认类型,您可以从其他方面考虑,它们被视为不完整类型
根据您的代码库,您可能不必专门化每个子类。这完全取决于它们是如何构造的,以及它们是否是完整类型。与您的问题无关,但我对混合运行时多态性工具(虚拟+继承)和静态多态性工具(模板)的想法有点困惑。也许你有正当的理由这么做@可悲的是,我不知道这两者之间的区别。最有可能的是,我只是在想,就像我说的,我的C++知识很稀少。每个派生类的虚拟方法都可以用覆盖来简单声明。问题是,《学习者声明》要求我为每个基类派生提供专门化声明。@Horus ah okay不确定,因为您显示的代码量很小。至于静态断言(…),这不是我的优势之一,至于部分专业化。。。首先,谢谢你的回复。然而,很可能是因为我没有正确地表达自己,这不是问题所在。请看我和方济各格勒在Op(我的)初始帖子上的评论。谢谢你的帮助。我的问题的答案可以在这里找到:
class D3 : public Base {
private:
unsigned int _x;
public:
explicit D3( unsigned int x ) : _x( x ) {}
virtual void doSomething() override {
std::cout << "D3's doSomething was called: constructed with " << _x << std::endl;
}
};
{
Learner<D3> ld3; // compiler error
Learner<D3> ld3( 5 ); // compiler error
Learner<D3> ld3( D3( 5 ) ); // compiler error
D3 d3(5);
Learnder<D3> ld3( d3 ); // compiler error
}
template<>
class Learner<D3> {
private:
D3* _d3;
public:
explicit Learner( unsigned int x ) {
_d3 = new D3( x );
}
explicit Learner( D3 d3 ) {
_d3 = new D3( d3 );
}
~Learner() {
if ( _d3 != nullptr ) {
delete _d3;
_d3 = nullptr;
}
}
void caller() {
_d3->doSomething();
}
};
{
Learner<D3> ld3a( 7 );
ld3a.caller();
D3 d3( 5 );
Learner<D3> ld3b( d3 );
ld3b.caller();
}