簡體   English   中英

如何使父類不重復已執行的祖父方法

[英]How to make it so parent classes don't repeat a grandfather method that was already executed

我們有一個孩子 class practicante ,他繼承了 2 個班級: estudianteempleado ,並且都繼承了祖父級persona 它們都有que_eres()方法,該方法將 class 寫成 object(僅舉個例子):

#include <iostream>
using namespace std;

class persona
{
    public:
    void que_eres() { cout<<"Soy una persona."<<endl; }
};

class estudiante: public persona
{
    public:
    void que_eres()
    {
        cout<<"Soy un estudiante."<<endl;
        persona::que_eres();
    }
};

class empleado: public persona
{
    public:
    void que_eres()
    {
        cout<<"Soy un empleado."<<endl;
        persona::que_eres();
    }
};

class practicante: public estudiante, public empleado
{
    public:
    void que_eres()
    {
        estudiante::que_eres();
        empleado::que_eres();
    }
};

int main()
{
    practicante jose;
    jose.que_eres();
}

結果是:

Soy un estudiante.
Soy una persona.
Soy un empleado.
Soy una persona.

還不錯,但是如果Soy una persona只寫一次就更好了(也就是說,祖父的que_eres()方法只執行一次)。 那可能嗎?

例如,在 Python 中我們可以這樣做:

class persona:
    def que_eres(self): 
        print("Soy una persona.")

class estudiante(persona):
    def que_eres(self): 
        print("Soy un estudiante.")
        super().que_eres()

class empleado(persona):
    def que_eres(self): 
        print("Soy un empleado.")
        super().que_eres()

class practicante(estudiante,empleado):
    def que_eres(self): 
        super().que_eres()

jose = practicante()
jose.que_eres()

結果只是:

Soy un estudiante.
Soy un empleado.
Soy una persona.

這是因為您在任何practicante中都有兩個persona實例:一個用於estudiante ,一個用於empleado ,而您在任何地方都沒有說過它總是相同的persona 在線演示)。

如果您希望所有這些persona都相同。 這被稱為 菱形問題 您需要為每個繼承persona的中介 class 使用public virtual inheritance。

但還有更多:因為只有一個虛擬基地,所以您需要小心。 這意味着practicante需要提供persona構造函數,否則編譯器將不知道構造函數的estudianteempleado調用中的哪一個具有優先權。 當然,如果你只有默認的構造函數,這幾乎可以按原樣工作(在線演示):

class estudiante: public virtual persona
{
    public:
        ...
};
class empleado: public virtual persona
{
    public:
        ...
};

同樣,您必須通過避免您使用的機制上游調用來確保沒有雙重調用,並讓不同的子類合作打印它們只打印一次。 一個簡單的技巧可能是將字符串參數(默認為""s )傳遞給que_eres()以構建要在調用中打印的字符串,並且只讓基數 class 打印它。 如果您不想更改que_eres()的簽名,您當然可以使用輔助 function。

例如,這里有一個在基礎 class 中只有一個que_eres()的實現,它使用每個 class 覆蓋的虛擬quien_soy()來構建表示字符串。 然后,虛擬基數必須確保它們在字符串中只出現一次。 在線演示

class persona
{
    protected:
        virtual string quien_soy(string x=""s) {
            const auto s="Soy una persona.\n"s; 
            auto p=x.find(s);
            if (p==string::npos)
                x += s;
            else {
                x = x.substr(0,p)+ x.substr(p+s.size()) +s;
            }
            return x;
        }
    public:
        void que_eres() { cout<<quien_soy() <<endl; }
        virtual ~persona() {}
};

class estudiante: public virtual persona
{
    protected:
        string quien_soy(string x=""s) override
        {
            return persona::quien_soy(x+"Soy un estudiante.\n");
        }
};

class empleado: public virtual persona
{
    protected:
        string quien_soy(string x=""s) override
        {
            return persona::quien_soy(x+"Soy un empleado.\n");
        }
};

class practicante: public estudiante, public empleado
{
    protected:
        string quien_soy(string x=""s) override
        {
            return empleado::quien_soy(estudiante::quien_soy(x+"Soy un praticante, por consiguiente:\n"));
        }
};

所有這些使得多個 inheritance 不像第一眼看上去那么微不足道,至少在鑽石表殼中是這樣。

提示:在現實生活中,角色就是角色。 estudiante 和 empleado 不是一個人,而是一個人承擔的角色。超過 inheritance 的組合會使這更現實,讓角色有可能在他們的生活中改變角色;-)

暫無
暫無

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

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