公开继承自基类,私下继承自派生类

Publicly inherit from base class, privately inherit from derived class

本文关键字:继承 派生 基类      更新时间:2023-10-16

奇怪的继承情况:

class Base
{
public:
public virtual foo() = 0;
};
class A : public Base
{
public:
public virtual foo() override;
protected:
int bar;
};
class B : public A//something like 'public Base, protected A'
{
public:
public virtual foo() override;
};

基本上,B可以继承A的所有内容,但只能"可见"(并且只能强制转换为)Base。基本上,我想在B中使用a的一些功能,但希望B在语义上与a:不同

B b;
Base* valid_ptr = &b;//want this to be ok
A* invalid_ptr = &b;//want this to be invalid
A& invalid_ref = b;//want this to be super invalid
A prevent(b);//want this to not be allowed to happen   

首先,只有当A从Base派生时,代码才能编译。如果Base对所有人都是公共的,并且A受到保护,那么唯一的方法就是不通过A将Base继承给B。

由于A不能通过B观察,因此解决方案可以是

class A: public Base 
{ ... };
class B: public Base 
{
A a;
public:
...
};

如果在B中存在两个Base实例(一个作为B的基,另一个与a成员一起出现)是不可接受的,那么另一种方法可以是通过虚拟基:

class A: 
public virtual Base 
{ ... };
class B:
public virtual Base,
protected A
{ ... };

这将使A通过B不可见(不能隐式转换为A),但在A和B之间只有一个共同的碱基。

在所有情况下,共享虚拟库的使用都是一个常见的习惯用法,对象通过成员函数优势(所谓的"堆叠平行四边形继承")或通过任意数量的接口("菱形对象")共享部分实现。

OOP纯粹主义者倾向于不喜欢这些数字,但这些数字是适当的C++公民(即使在其他受OOP启发的经典语言中找不到任何表示,因为缺少多重继承!)

我认为您正在处理组合与继承的问题。

你可能让B从Base继承,并使用合成技术来利用a.

否则,对于您列出的问题,您可能会考虑使构造函数不可访问:

class A
{
public:
A() {};
};
class B : private A
{
public:
B() {};
};

例如(MSVC2012)

错误C2243:"类型转换":存在从"B*"到"A*"的转换,但无法访问