2016-07-28 56 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 
}