[英]How to make it so parent classes don't repeat a grandfather method that was already executed
我們有一個孩子 class practicante
,他繼承了 2 個班級: estudiante
和empleado
,並且都繼承了祖父級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
構造函數,否則編譯器將不知道構造函數的estudiante
和empleado
調用中的哪一個具有優先權。 當然,如果你只有默認的構造函數,這幾乎可以按原樣工作(在線演示):
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.