这里违反了封装的概念吗?

3
#include<iostream>

class A {
public:
  int a;
protected:
  void func() {
  std::cout<<"protected member"<<endl;
  }
};

class B:public A
{
public:
  using A::func;  //Isn't this violation of encapsulation?
};

int main(){
B b;
b.func();
return 0;
}

为什么上面的代码可以成功运行?

它不违反封装的概念吗?

如果我错了,请纠正我。


"封装"是什么意思? - Kerrek SB
由B的设计者决定使用什么接口,包括提供对A的受保护成员的访问。 - Bo Persson
我看到你也发布了关于Java的问题。当涉及到编程的“概念”时,C++和Java有很多不同之处。它们在许多方面都是非常不同的语言。这就是其中之一。 - Bo Persson
保护继承仅意味着A的公共成员在B中也将受到保护。私有继承意味着B中的所有内容都将是私有的。无论您做什么,A的所有成员也将成为B的成员。 - Bo Persson
非常感谢您澄清我的误解。 - Shubham Batra
显示剩余2条评论
2个回答

4
这是一个有趣的问题,我认为它突显了c++中封装的一个重要而经常被忽视的方面。
我的答案是“是的,封装已经被破坏了,但不是你想象的那个地方”。实际上违反的是在第一次声明方法时将其设为protected
你的代码很好地展示了受保护的子类关系的问题...他们可以轻易地去除保护。换句话说,如果你将成员设置为protected,那么你可能会将其设置为public,因为在现实中,如果你的子类希望这样做,protected就等同于public
这在实践中意味着什么?
这意味着如果你将成员函数设置为protected,它将永远成为你的类的接口的一部分。因此,你必须像对待任何其他公共成员函数一样认真对待它,并且确实将其视为公共成员函数。
这意味着它应该尽可能无状态,尽可能少的前提条件,并且如果你改变了实现,那么对于对象作为整体的逻辑效果必须保持不变。

谢谢,这正是我想要的解释。 - Shubham Batra
的确。将实现细节声明为“protected”似乎是初学者常犯的错误。我记得当我刚开始学习C++时也犯过这个错误。随着多年的经验积累,后来发现“protected”几乎没有什么用处。几乎所有成员都应该是“public”或“private”。 - Christian Hackl

2
您展示的示例代码并不违反封装性,因为子类可以在继承的基础上添加公共成员,并且也可以访问它们继承的受保护成员。
在您的情况下,BA的子类,决定添加一个名为func的新成员函数,其实现恰好包括对A::func的单次调用。
通常来说,protected成员应被视为类的接口的一部分,与其public成员一起。尽管它们的可见性仅限于子类,但受保护成员并不是类的实现的一部分,因为对受保护成员命名或语义的任何更改都需要与所有子类的更改协调一致。

func()被保护了怎么办? - Shubham Batra
@ShubhamBatra:这有什么问题吗?protected字面意思是派生类可以访问该符号,所以没有问题。你是不是把protectedprivate搞混了? - Lightness Races in Orbit
@ShubhamBatra 只有 A::func() 是受保护的;B::func() 并没有被类 B 的设计者明确地保护。 - Sergey Kalinichenko
@ShubhamBatra - B 也可以添加 void another_func() { func(); }。有什么区别吗? - Bo Persson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接