我一直对以下事实感到困惑:大多数OOP语言(或者更确切地说,C++)使您在界面中定义私有方法/成员(通过接口我的意思是类声明 - 似乎我感到困惑).这不是显示类的实现细节,而是违背封装的想法吗?
有没有一个很好的理由让我失踪?
650*_*502 12
对于C++,这是一个实现问题.
C++编译器必须能够通过仅查看类声明而不是实现来生成使用类的代码.编译器需要的一个非常重要的事情是类的实例的大小,因为C++通过嵌入而不是通过存储对单独对象的引用来处理对象中的子对象.为了能够构建对象(例如struct X { Y y; Z z; }),必须事先知道所有子对象(例如Y和Z)的大小.
此问题的解决方法是使用"pimpl"模式(也称为"编译器防火墙"模式),该模式允许您将所有内部详细信息隐藏在类的用户之外.不幸的是,它带来了一些运行时的额外成本,但大部分时间它都可以忽略不计.使用这种方法,公共对象将始终具有指针的大小,并且将使用额外的间接访问实例中的所有数据...优点是您可以添加私有数据成员,并且该类的用户不需要重新编译(例如,如果您的类在DLL中,则允许保持二进制兼容性).
能够在实现部分中声明私有方法(没有数据)是可能的,而编译器没有任何增加的复杂性,但C++设计者认为最好为类保留一个单独的声明.
实际上,即使只是添加私有方法也可能会影响许多实现中类实例的大小(例如,如果私有方法是类中唯一的虚方法).
C++是我所知道的唯一这样做的语言; 值得注意的是,有几种功能语言严格区分公共和私有接口的声明.请注意,C++在声明和定义之间有所区别:您只需要在接口中声明私有函数,而不是定义它们.
对于成员变量和虚函数,有一个简单的技术原因:它们影响类的物理布局.由于这种布局在翻译单元之间需要相同,因此所有单元都需要知道布局 - 因此需要知道类的物理构成.
我怀疑你还需要在C++中公开声明非虚函数以保持其一致性:否则,你必须在不同的地方声明不同的函数,这取决于它们是否是公共的和/或虚拟的.
您可以通过使用handle-body惯用法(也称为美观不太吸引人的名称"PIMPL")来规避此限制,但这会增加解决方案的复杂性.