使用受保护的继承公开基类转换函数

Posted

技术标签:

【中文标题】使用受保护的继承公开基类转换函数【英文标题】:Making Base Class Conversion Functions Public with a Protected Inheritance 【发布时间】:2021-07-22 02:02:03 【问题描述】:

我有一个继承自另一个的类。我不希望此类的用户意外地在子对象上使用基类函数。显而易见的答案是使继承受保护或私有。

但是,我确实希望将子对象隐式转换为基类。此强制转换的默认实现在大多数情况下是隐藏的,因为它被赋予受保护/私有状态,并且尝试定义用户转换会引发警告: "converting ‘B’ to a reference to a base class ‘A’ will never use a type conversion operator [-Wclass-conversion]"

很公平。由于这条路对我关闭,我必须转过来问:有没有办法将默认类型转换重新分类到公共空间,以便隐式转换可以继续存在?

作为我正在努力工作的一个例子:

class A

public:
    A()
    
        
    
    A(A& otherA)
    
        
    
;

class B : protected A

public:
    operator A& ()
    
        return *this;
    
    
;

int main() 
    B guy;
    A otherguy(guy);

遗憾的是,我不能只将基类中的违规函数声明为受保护:如果用户显式转换为该基类,我希望它们可用。在我的特殊情况下,B 不包含任何数据,只是 A 周围的便利/安全包装,因此我无需担心通过允许此转换来切片或以其他方式丢失任何信息。我只是不希望用户将后端 API(目前通过公共继承公开)误认为是对用户更友好的包装 API 的一部分。

【问题讨论】:

如果目标是让用户确认他们正在转换,您是否考虑过只使用一个显式函数,例如B.convert_to_a?必须写 guy.convert_to_a() 清楚地表明我理解转换的后果。 我有一个这样的函数,它提供了我希望他们进入后端 API 的显式转换。但是,我不想重写当前隐式转换性质的 B 的每次使用来调用该显式函数。许多请求 A 的函数目前在我的代码库中接受 B。我也不想规范化调用显式转换,因为在每种情况下都需要它。 【参考方案1】:

我不认为你可以按照你要求的方式做你想做的事

我会使用封装而不是继承:

class A 
public:
    T func1(); // should be visible via B
    void func2(); // should not be visible via B
;

class B  // note: not inheriting from A
    A base; // B explicitly defines its "base class sub-object"
public:
    // provide access to base class sub-object
    operator A&()  return base; 

    // provide access to func1
    T func1()  return base.func1(); 
;

void use(A &a)  a.func2(); 

int main()  
    B b;

    b.func1(); // no problem
    // b.func2(); // won't work;

    use(b);    // no problem. Uses our conversion operator

【讨论】:

以上是关于使用受保护的继承公开基类转换函数的主要内容,如果未能解决你的问题,请参考以下文章

继承和友元函数,从基类访问受保护的成员

获取指向基类受保护成员函数的函数指针

详解C++中基类与派生类的转换以及虚基类

访问继承的函数

子类真的继承私有成员变量吗?

面向对向之继承和扫描顺序