[英]Do these two classes violate encapsulation?
class X
{
protected:
void protectedFunction() { cout << "I am protected" ; }
};
class Y : public X
{
public:
using X::protectedFunction;
};
int main()
{
Y y1;
y1.protectedFunction();
}
這樣我就可以公開基類的一個功能。
你是自己做的。
你可以寫
class Y : public X
{
public:
void doA()
{
protectedFunction();
}
};
int main()
{
Y y1;
y1.doA();
}
我認為沒有理由擔心它。
受保護的函數是繼承樹中可重用邏輯的一部分。 你可以隱藏它們,如果有一些內部邏輯或限制,或者像你的情況那樣你可以暴露它,如果你確定這不會傷害任何人。
是的,這就是為什么受保護已經受到了公平的批評。
C ++的創建者Bjarne Stroustrup在他的優秀着作“C ++的設計和演變”中對此感到遺憾:
我對受保護的一個擔憂正是因為它太容易使用一個共同的基礎,就像人們可能已經習慣使用全局數據一樣....回想起來,我認為受保護是一個“好的論據”和時尚克服的情況我更好的判斷力和接受新功能的經驗法則。
我認為正是Stroustrup本人說C ++中內置的封裝和數據完整性功能旨在讓誠實的人保持誠實,而不是阻止犯罪分子。
編號protectedFunction()受保護。 您可以從派生類中自由調用它,因此您可以直接從Y的公共成員調用它,並從main()調用此公共成員。
如果您可以使用私有方法完成此操作,則會出現問題...(編輯更清楚一點)。
從語言的角度來看,與在派生對象中創建委托方法相比,這不僅僅是對封裝的違反:
class Y : public X
{
public:
void protectedFunction() {
X::protectedFunction();
}
};
一旦方法受到保護,它就會被提供給派生類,以便按照自己的意願去做。 using
聲明的意圖不是更改繼承的方法訪問,而是避免方法隱藏的問題(如果定義了不同的重載,則X
中的公共方法將隱藏在類型Y
)。
現在,事實是,由於語言規則,它可以用於更改“已使用”方法的訪問級別,如您的示例所示,但這並沒有真正打開系統中的任何漏洞。 最后,派生類不能做任何比以前更多的事情。
如果實際問題是從設計的角度來看特定用法是否違反封裝(這里的設計是應用程序設計,而不是語言設計),那么很可能是肯定的。 與公開內部數據或方法的方式完全相同。 如果它被設計為受X
的初始設計者保護,那么很可能Y
實現者不希望它被公開......(或者為同一目的提供委托方法)
沒有。
要使用公共方法,您應該有一個Y
的實例,這將不起作用:
int main()
{
X y1;
y1.protectedFunction();
}
如果新定義中的Y暴露了一個新接口,那么Y.X仍然受到保護。
類設計者應該知道聲明一個成員函數或變量(雖然所有變量應該是私有的,真的)作為受保護的大多數與聲明它是公開的(因為你展示它很容易訪問受保護的東西)。 考慮到這一點,在基類中實現這些功能時應注意考慮“意外”使用。 這不是對封裝的違反,因為您可以訪問它並公開它。
受保護只是一種宣傳公開的更復雜的方式!
不,我真的沒有看到問題。
而不是using
,你可以做到這一點:
class X
{
protected:
void protectedFunction() { cout << "i am protected" ; }
};
class Y : public X
{
public:
void protectedFunction() { X::protectedFunction(); }
};
任何類都可以接受任何可見的成員,並決定公開公開它。 這樣做可能是糟糕的課堂設計,但它肯定不是語言中的缺陷。 私有或受保護成員的整個要點是,類本身必須決定誰應該訪問該成員。 如果班級決定“我將給全世界訪問”,那么這就是班級的設計方式。
如果我們遵循您的邏輯,那么getter和setter也會違反封裝。 有時它們會這樣做。 但不是因為語言被打破了。 僅僅因為你選擇設計破碎的課程。
通過使成員受到保護,您可以為派生類提供對成員執行任何操作的自由。 他們可以看到它,因此他們可以修改它,或公開公開它。 當您保護成員時,您選擇使這成為可能。 如果你不想那樣,你應該把它變成私人的。
就個人而言,我認為這個問題應該更多地回答為設計問題而不是技術問題。
我會問,“首先,受保護的方法有什么意義?” 它是一個只有子類應該調用的方法,還是一個子類應該覆蓋的方法? 但是,它可能是一種在通用基類中不期望的方法,但可能在子類中預期。 對於基類的客戶端,他們從未知道該受保護的方法。 子類的創建者選擇擴展合同,現在受保護的方法是公開的。 問題確實不應該是C ++允許的,但它適合你的課程,合同和未來的維護者。 當然它可能是一種難聞的氣味,但實際上你需要使其適用於所涉及的用例。
如果確實將受保護的方法設為公開,請確保為維護者正確提供內部文檔,說明為何做出此特定決策的理由。
一般來說,為了安全起見,作為前面提到的貢獻者,您可能希望在子類中使用委托函數(具有不同的名稱)。 因此,不是“get(int)”而是“getAtIndex(int)”或其他東西。 這使您可以更輕松地重構/保護/抽象/記錄將來的文檔。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.