前言
由于工作需要,最近在读folly库src,在阅读源码过程中产生了一些关于private继承,static_cast,friend之间的疑问。
前置知识
private继承
C++在业务逻辑中很少涉及private继承,实际上private继承仅仅是一种实现技术,如果class d以private形式继承class b,这说明d仅仅为了采用某些b中已经存在的特性,而不是b和d有任何观念上的交集。
一般来说,private继承主要用于EBO(Empty Base Optimization)。
更多信息可以参考Effective C++中关于private继承的说明。
static_cast
四种类型转换之一,相较于dynamic_cast
,static_cast
在做向下类型转换时(Base class to Derived class),不验证正确性。
当用作向下转换时,static_cast
需要保证待转换对象间存在public继承关系,否则无法通过编译。
1 | class B { |
case
根据前置知识,下文内的代码无疑是无法通过编译的:
1 | template<typename T> |
但是,如果在Derived
内添加friend base class
,则可正常通过编译
1 | template<typename T> |
疑问
我对friend
的了解仅仅是改变了class之间的符号访问关系,为什么通过增加friend修饰,可以做到cast private base to derived?
一些猜想与结论
根据 https://stackoverflow.com/questions/56673706/inaccessible-base-class-despite-friendship
得到了一些初步的结论:
简单来说,private继承令d无法访问b的内部具体实现(这也是private的特性),从而d*
与b*
不具备相互转换的能力(inaccessible-base-class)。
但加上friend后,在指定的上下文内d可以访问b的内部实现,因此static_cast是合法的。示例如下:
1 | template<typename T> |