2016-04-28 80 views
0

我正在學習C++。我有一個基類Base及其派生類Derived。他們將push_back分成std::vector<Base*> vec。假設vec[0] == &Basevec[1] == &Derived,我可以切換功能vec[0]vec[1]沒有虛擬功能。代碼在這個問題的最後。有沒有更好的方式沒有虛擬功能?我想要純數據類,我想添加非成員函數來修改它們以避免修改數據類的代碼。非常感謝你。有沒有更好的方法來切換沒有虛擬功能的功能?

class TypeInterface { 
public: 
    virtual int type(void) = 0; 
    virtual ~TypeInterface() {} 
}; 

class Base : public TypeInterface { 
public: 

    static constexpr int type_ = 1; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Base() {} 
}; 

class Derived : public Base { 
public: 

    static constexpr int type_ = 10; 
    virtual int type(void) { 
     return type_; 
    } 

    virtual ~Derived() {}; 
}; 

void Function(Base* ptr) { 
    std::cout << "function for Base" << std::endl; 
} 

void Function(Derived* ptr) { 
    std::cout << "function for Derived" << std::endl; 
} 

void SwitchFunction(int type, void* ptr) { 
    switch (type) { 
    case 1: { 
     Base* original_type_ptr = static_cast<Base*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    case 10: { 
     Derived* original_type_ptr = static_cast<Derived*>(ptr); 
     Function(original_type_ptr); 
     break; 
    } 
    default: 
     std::cout << "invalid type(=" << type << ")" << std::endl; 
    } 
} 

void test_function_selecter(void) { 

    Base b; 
    Derived d; 

    std::vector<Base*> vec; 

    vec.push_back(&b); 
    vec.push_back(&d); 

    for (auto e: vec) { 
     SwitchFunction(e->type(), e); 
    } 

} 
+1

你的代碼有未定義的行爲。那些是一些討厭的演員。理想情況下,當你剛剛學習C++時,你根本不應該使用指針或轉換... –

+1

如何將函數存儲爲變量?如果它用於所有實例,則可以將其設置爲靜態。 std :: function myFunc = [](void){// do something} – Striker

+0

謝謝你,Kerrek SB。我試圖找到你的擔心,我想你可能會擔心我可能會使用錯誤的類型和void *組合。在我的情況下,SwitchFunction(e-> type(),e)具有固定格式。所以我希望我可以避免選錯組合。 – mora

回答

1

你不需要「type_」或「整型(無效)」,而不是使用「typeid的」

void SwitchFunction(Base* ptr) 
{ 
    auto&& type = typeid(*ptr); 
    if (type == typeid(Base)) 
     Function(dynamic_cast<Base*>(ptr)); 
    else if (type == typeid(Derived)) 
     Function(dynamic_cast<Derived*>(ptr)); 
    else std::cout << "invalid type(=" << type.name() << ")" << std::endl; 
} 

可惜,這可能不回答你的問題正確,因爲它需要「基地」有一個虛擬功能(例如析構函數,當你的類型涉及層次結構時,通常建議使用虛擬函數)

+0

謝謝Issac。恐怕我無法告訴你我的觀點。重點是我想添加函數來處理數據類而不修改數據類。如果我使用虛擬類,則需要爲數據類添加(並修改)虛擬功能。所以虛擬析構函數對我來說可以。再次感謝您的解決方案。但讓我多問你一點。從速度表現的角度來看,你的方式還是我的方式,更好還是相同? – mora

+1

&more可能大致相同,但如果你真的關心我會建議測試它,我個人不會打擾,除非你擁有的類型數量非常大,在這種情況下,'switch'語句可能會執行'if/else if'語句(你不能使用'switch'和'typeid'),當然我的解決方案在你的對象中佔用更少的空間,這可能比次要的性能差異更重要。 – Isaac

相關問題