2016-07-28 78 views
2

我有具有虚拟功能的基类:重新实现从基类的虚拟功能在派生模板

class Base { 
    ... 
    virtual void myFunction() { assert(0 && "not implemented yet"); } 

} 

和派生(模板)类基地:

DerviedClass.hpp :

Template<typename T> 
class DerivedClass : public Base, public T { 

    ... 
    void myFunction(); 

} 

DerivedClass.cpp:

template <> 
void DerivedClass<ClassA>::myFunction() { 
//Something ClassA is suppose to do 
} 

编译。但是,当我尝试实例化一个DerivedClass<ClassB>我得到的错误:

IProject.o:-1: erreur : undefined reference to `DerivedClass<ClassB>::myFunction()' 

为什么我有这样的错误?为什么它不需要Base::myFunction而不是强迫我在DerivedClass或专用功能DerivedClass::myFunction中实现通用myFunction

注:在myFunction的断言是因为ClassB不应该在runtime调用myFunction。例如,如果myFunctiongetRadius,DerivedClass<Circle>::getRadius()是好的,但不应该调用DerivedClass<Square>::getRadius()

注2:其他主题,我发现并不清楚这点

+0

您可能想要重新考虑您的设计以禁止DerivedClass :: getRadius()。 – Jarod42

+1

'DerivedClass :: getRadius()'不应该在第一个地方存在。 –

+0

我做了这个设计,当我想从基类调用一个函数时,无需'dynamic_cast'就可以将所有的DerivedClass操作为Base。 (有很多派生类有很多需要调用的函数) – ElevenJune

回答

2

为什么不采取Base::myFunction而不是强迫我实​​现DerivedClass通用myFunction或专门的功能DerivedClass::myFunction的?

是你逼的是自己,由该声明:

void myFunction(); 

充分考虑专业类模板,这将有或没有覆盖myFunction有条件生成类,如:

template <typename T> 
class DerivedClass : public Base, public T { 
    // not overriding  
}; 

template <> 
class DerivedClass<ClassA> : public Base, public ClassA { 
    void myFunction() override; 
}; 

template <> 
void DerivedClass<ClassA>::myFunction() { 
    // something ClassA is supposed to do 
} 

如果有一些常见的东西,你可以把它放在:

template <typename T> 
class DerivedClassCommons : public Base, public T { 
    // common stuff 
}; 

然后重构DerivedClass以使用此类模板的单一继承。

这就是你的问题,但正如其他人所指出的,我认为你有一个更大的设计问题。

+0

所以如果我这样做,我必须在DerivedClass中实现一个通用函数? 'template inline DerivedClass :: myFunction()'?它将永远不会调用Base :: myFunction()用于任何在'DerviedClass '中使用的T? – ElevenJune

+0

@ElevenJune新增了一个我正在谈论的例子。 – LogicStuff

+1

现在我不了解!谢谢 ! – ElevenJune

1

对于所有类型,函数已经为声明为。定义可能来自任何地方,包括其他编制单位。只有在函数被引用时才需要定义 - 并且在构建过程中虚拟函数被(隐式地)引用。

+0

我认为我明白你的答案。如果我没有提及任何DerivedClass ,我将永远不会有编译问题,因为不会生成DerivatedClass 的代码,并且永远不会尝试查找myFunction。但是如果我必须在代码的某个地方使用DerivedClass ,有没有办法调用Base :: myFunction()? – ElevenJune

+0

@ElevenJune你的派生类重新声明它从基地继承的功能。因此,要匹配该声明,必须提供一个定义。如果你不想重写基本版本,那么你需要......不要在派生版本中重新声明它。这与任何其他类完全一样:事实上,您的派生类在这里恰好是一个模板是完全偶然的。 –

+0

我现在明白了,谢谢! – ElevenJune

2

修复编译器错误(不设计错误)的另一种方法是将myFunction定义移动到衍生的模板:

class Base { 
    virtual void myFunction() = 0; 
} 

template<typename T> 
class DerivedClass : public Base, public T { 
    void myFunction() { 
     throw "not implemented, go away"; 
    } 
} 

,然后专注只有你需要的方法

template <> 
void DerivedClass<ClassA>::myFunction() { 
//Something ClassA is suppose to do 
}