举例说明我的问题:
class Base
{
protected:
int x{ 0 };
};
class DerivedClass1 : public Base
{
};
class DerivedClass2 : public DerivedClass1
{
public:
int getX() const
{
return x;
}
};
int main()
{
DerivedClass2 d2{};
int x{ d2.getX() };
return 0;
}
我可以访问Base
类中受保护的DerivedClass2
成员,尽管Base
的受保护成员只能在DerivedClass1
中更改。通过将Base
中的变量继承到DerivedClass1
,将形成一个类,DerivedClass2
不得操纵它。在C#中,这可以使用private protected
关键字,但是如何在C ++中处理它?
protected
的想法是允许所有派生类访问这些成员。
虽然这是一个非常灵活的语言特性,但它在封装中造成了严重的弱点,这鼓励打破Liskov Substitution Principle(更准确地说是历史约束,因为派生类可以改变基础对象的状态而不通过基类原语) 。
如果你想要更强的封装和限制访问,你需要去private
。这确保只能使用公共接口访问基类的内部状态。 (请注意,虽然它确保了历史约束,但它本身并不保证LSP)。结果是没有派生类获得访问权限。不是最初的推导,也不是后来的推导。
你想要什么,是一种中间:弱封装,但不是太弱。这在C ++中不存在。而且我不确定它会加强你的设计。
但是如果你在特殊情况下需要这个限制,可以有一个解决方法,玩名称查找:
class DerivedClass1 : public Base
{
private:
using Base::x;
// In DerivedClass1 you can still use x.
};
// But it will fail to compile in Derived2
但我个人不建议这样做。这很容易出错(你可能会忘记一个兄弟姐妹中的using
)。编译器错误消息可能会产生误导。无论如何,私人产生更强大的设计。
您可以将数据成员声明为private
并使用friend
-declarations显式指定哪些类可以访问它:
class Base
{
friend class DerivedClass1;
private:
int x = 0;
};
class DerivedClass1 : public Base
{
void test() {
cout << x; // OK: DerivedClass1 is a friend of Base
}
};
class DerivedClass2 : public DerivedClass1
{
public:
int getX() const
{
return x; // ERROR: x is a private member
}
};
继承'私人'基地:
class DerivedClass1 : private Base
{
};
编辑:通过DerivedClass1中的公共成员或受保护成员公开Base中的公共成员或受保护成员。然后,DerivedClass1可以完全控制从DerivedClass1继承的类可以访问和不能访问的Base成员。
这是否是一个好的解决方案取决于Base的复杂性。