簡體   English   中英

如何處理具有相同方法的不同類?

[英]How to deal with different classes which have the same method?

例如,我有 2 個類(實際上,它更多,這就是我問這個問題的原因)使用相同的方法:

class class1{
public:
    void init(){
        //something
    }
    void dostuff(){
        //something
    }
//
};

class class2{
public:
    void init(){
        //something
    }
    void dostuff(){
        //something
    }
//
};

現在是第三個,我想以相同的方式處理這兩個類:

class upclass{
public:
    upclass(class12* argclass){
    myclass=argclass;
    myclass->init();

    }
    void domorestuff(){
        myclass->dostuff();
    }
private:
    class12* myclass; //pointer to class 1 OR class 2
};

我現在的問題是,我是否需要多個構造函數和多個聲明才能使其工作,還是有辦法解決它? 甚至可以在沒有預處理器指令的情況下使“class12”成為這些類型的空間管理員嗎?

您可以通過std::variant顯式編寫“存儲其中之一”並通過std::visit獲取實際類型(在需要時):

#include <variant>

using class12 = std::variant<class1*, class2*>;

class upclass {
public:
    upclass(class12 argclass): myclass{argclass} {
        visit([](auto classn) { classn->init(); }, myclass);
    }
    void domorestuff() {
        visit([](auto classn) { classn->dostuff(); }, myclass);
    }
private:
    class12 myclass;
};

如果這些visit過於重復,您可以考慮編寫一個漂亮的 API 來隱藏它們:

class prettyclass12: public std::variant<class1*, class2*> {
private: // both g++ and clang want variant_size<>, a quick hack:
    auto& upcast() { return static_cast<std::variant<class1*, class2*>&>(*this); }
public:
    using std::variant<class1*, class2*>::variant;
    void init() { visit([](auto classn) { classn->init(); }, upcast()); }
    void dostuff() { visit([](auto classn) { classn->dostuff(); }, upcast()); }
};

class prettyupclass {
public:
    prettyupclass(prettyclass12 argclass): myclass{argclass} { myclass.init(); }
    void domorestuff() { myclass.dostuff(); }
private:
    prettyclass12 myclass;
};

很抱歉,這是一個廣泛的領域,確實有很多可能的解決方案。

但我想我們正在談論面向對象的編程、派生和多態函數。 您所描述的內容通常會通過 class 層次結構來解決。

您有一個帶有虛擬(多態)功能的基礎 class。

然后從這個基礎 class 派生其他類,並從基礎 class 覆蓋虛函數。

第三步,在運行時動態創建派生類的一些實例,並將新創建的類(它們的地址)存儲在指向基礎class 的指針中。

稍后,您可以通過基本 class 指針調用任何虛擬覆蓋的 function。 幕后機制將為您調用正確的 function。


此外。 您定義了一些 function init 這樣的 function 名稱暗示使用類構造函數。 這將按正確的順序自動調用。 首先是基礎 class 構造函數,然后是派生的 class 構造函數。

請看下面的例子:

#include <iostream>
#include <string>

class Base {
    std::string baseName{};
public:
    Base() {        // Do initialization stuff
        baseName = "Base";
        std::cout << "\nConstructor Base\n";
    }
    virtual void doStuff() {     // virtual function
        std::cout << baseName << '\n';
    }
};
class Derived1 : public Base {
    std::string derivedName{};
public:
    Derived1() : Base() {         // Do initialization stuff
        derivedName = "Derived1";
        std::cout << "Constructor Derived1\n";
    }
    void doStuff() override {       // Override virtaul function
        std::cout << derivedName << '\n';
    }
};
class Derived2 : public Base {
    std::string derivedName{};
public:
    Derived2() : Base() {        // Do initialization stuff 
        derivedName = "Derived2";
        std::cout << "Constructor Derived2\n\n";
    }
    void doStuff() override {       // Override virtaul function
        std::cout << derivedName << '\n';
    }
};

int main() {
    Base* base = new Base();

    Base* derived1 = new Derived1(); // Store in base class pointer
    Base* derived2 = new Derived2(); // Store in base class pointer

    base->doStuff();
    derived1->doStuff(); // Magic of polymorphism
    derived2->doStuff(); // Magic of polymorphism
}

Base class 指針將接受從 Base 派生的所有類。

請注意。 實際上,您不應該使用原始指針,也不應該以不同的方式使用構造函數。 這只是 fotr 演示。

但是,你需要閱讀幾本關於它的書才能完全理解。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM