2017-03-06 74 views
1

可以說我有一個基類A,我想要一個方法getName,它可以採用整數或字符串作爲參數。所以我創建:在C++中有多個參數類型的虛擬方法

virtual string getName(int index) = 0; 
virtual string getName(string key) = 0; 

現在,我想創建兩個不同的子類B和C.只有B需要getName(int index)和C只需要getName(string key)。 但是,如果我不覆蓋兩個子類中的兩種方法,則會出現錯誤。但如果我這樣做,那麼B和C將有一個空方法,因爲他們不需要另一個案例getName

我該如何克服這個問題?

+0

當您將使用類B和C,使用基本接口,如何維托裏奧·羅密歐的解決方案你會知道它是否支持帶int或字符串參數的getName? – marcinj

+0

@AlexandreTHOUVENIN我對此表示懷疑,定義可能不應該是'int'和'string'類型。 – George

+0

您能否添加一個'A'的使用示例?爲什麼你需要在同一個基類中同時使用'getName'重載? –

回答

-2

通過簡單地不使他們的純虛,但只是虛:

struct Blub 
{ 
    virtual void do1() {} // default definition 
    virtual void do2() = 0; //has to be overridden 
}; 
+0

我認爲OP至少需要在派生類中定義的兩種方法中的一種 – Nyashes

3

這聽起來像你真正想要的兩個不同的接口:一個支持getName(int)一種支持getName(string)

struct GetNameInt { 
    virtual string getName(int index) = 0; 
}; 

struct GetNameStr { 
    virtual string getName(string key) = 0; 
}; 

struct B : GetNameInt { /* ... */ }; 
struct C : GetNameStr { /* ... */ }; 

如果你真的需要具有相同接口的一個基類,你只知道在運行時是否需要一個stringint,你可能要使用std::variant

struct GetName { 
    virtual string getName(std::variant<int, string>) = 0; 
}; 
1

您沒有使用正確的繼承。我強烈建議閱讀更多關於SOLID principles

你需要A類分爲兩個類(接口) - Aa和Ab,其中aa將持有的getName(INT指數),並會有的getName(字符串鍵),如:

class A { 
//does not define neither of the getName methods 
} 

class Aa { 
    virtual string getName(int index) = 0; 
} 

class Ab { 
    virtual string getName(string key) = 0; 
} 

class B : A, Aa { 
    //inherits from A and defines string getName(int index) 
} 

class C : A, Ab { 
    //inherits from A and defines string getName(string key) 
} 
0

好,最好的,我可以拿出來保持一個共同的父B和C之間,同時仍然保持某種類型的安全性和編譯時檢查:

struct CommonA //protect this if possible 
{ 
    template<class type> 
    string getGenericName(type index); 
    virtual ~CommonA() {} 
}; 

template<class indexType> 
struct A : CommonA 
{ 
    virtual string getName(indexType index) = 0; 
}; 

struct B : A<int> 
{ 
    string getName(int index) override {cout << index << "\n"; } 
}; 
struct C : A<string> 
{ 
    string getName(string index) override {cout << index << "\n"; } 
}; 

template<class type> 
string CommonA::getGenericName(type index) 
{ 
    cout << "generic call: \n"; 
    return dynamic_cast<A<type>*>(this)->getName(index); 
} 

int main() 
{ 
    CommonA b = B(); 
    CommonA c = C(); 
    b.getGenericName(1); 
    c.getGenericName(string("hello world")); 
} 

注意,該解決方案是不是一個標準的面向對象的解決方案,但一個模板解決方案。

編輯:我的模板一<>類是與使用的模板,而不是名稱粘貼(名稱粘貼是邪惡的)

+0

將虛擬析構函數放入'CommonA'中,使用(並檢查)'dynamic_cast'而不是'static_cast'以獲得更好的類型安全性。 – Jarod42

+0

@ Jarod42完成後,如果您發現其他改進空間,請隨時進一步編輯 – Nyashes

+0

看起來像是過度工程給我的。在我看來,至少它混合了模板和繼承的味道。 – zett42