重新认识一下“私有继承”

被"私有继承"劝退?别急,它可能比你想象的更有用!

哈喽,大家好!👋

最近在啃C++继承这块硬骨头🦴 学完了public继承,感觉世界一片美好,父类的东西子类都能用,多爽!

然后,兴冲冲地翻到了"私有继承"(private inheritance)这一章......

🤯 瞬间感觉被泼了一盆冷水?

我当时就是这样!满心欢喜地写下代码:

cpp 复制代码
class Base {
public:
    void publicFunc() { cout << "我是public!" << endl; }
protected:
    void protectedFunc() { cout << "我是protected!" << endl; }
};

class Derived :private Base { // 私有继承!
public:
    void test() {
        publicFunc();      // 嘿,在类里面还能用
        protectedFunc();   // 嗯,protected也能用
    }
};

int main() {
    Derived d;
    d.test(); // 编译通过,没问题
    // d.publicFunc(); // ??? 编译错误!说好的继承呢?
    return0;
}

我的内心OS:

"不是吧阿sir?😱 我费老大劲继承过来,结果在main函数里,连父类最公开的public成员都访问不了了?那我还继承个寂寞啊?这private继承是不是个'废物'?🤷‍♂️"

相信不少小伙伴都有过类似的灵魂拷问。别急,我当时也这么想,直到我换了个角度,才恍然大悟!


换个思路,柳暗花明

后来我才明白,我们一开始就掉进了一个思维陷阱:我们总把继承看作是"接口继承"(Interface Inheritance),也就是"我是一个..."(is-a)的关系。

比如,DogAnimal的一种,所以我们用public继承,这样Dog对象也能像Animal一样被对待。

private继承,它压根就不是为了这个!它的潜台词是:

"我(子类)需要用你(父类)的功能来实现我自己,但我不想让外界知道我和你有这层关系。咱们是'实现继承'(Implementation Inheritance),也就是'我是用...实现的'(is-implemented-in-terms-of)。"

这就好比什么呢?

想象一下,你买了一辆酷炫的跑车🏎️。

  • public继承:就像这辆车是"法拉利"品牌。你开出去,大家都知道这是法拉利,可以享受法拉利的品牌效应(接口)。

  • private继承 :就像这辆车内部 装了一个非常强大的"博世"引擎。你(作为车主)知道这车跑得快是因为有博世引擎,你也可以在车里通过油门(子类成员函数)来使用引擎的动力。但是,对于车外的人来说,他们只知道你开的是一辆跑车,他们并不能直接访问或控制那个"博世"引擎。 引擎的功能被"私有化"了,成为了跑车实现"跑得快"这个功能的内部细节。

所以,private继承的核心价值在于:代码复用 + 接口隐藏


那它到底有啥用?看个栗子!

假设你正在写一个网络库,你需要一个Connection类来管理网络连接。恰好,C++标准库提供了一个Socket类,它有很多你需要的底层功能(比如connect(), send(), receive())。

方案一:组合(Composition)

cpp 复制代码
class Connection {
private:
    Socket socket; // 拥有一个Socket对象
public:
    void connectToServer(const string& ip, int port) {
        socket.connect(ip, port); // 调用内部socket的功能
    }
    void sendData(const string& data) {
        socket.send(data);
    }
};

方案二:私有继承(Private Inheritance)

cpp 复制代码
class Connection : private Socket { // 私有继承自Socket
public:
    void connectToServer(const string& ip, int port) {
        connect(ip, port); // 可以直接调用继承来的Socket成员
    }
    void sendData(const string& data) {
        send(data); // 同样可以直接调用
    }
};

看到了吗?

Connection类内部,两种方式都能复用Socket的功能。但private继承有一个微妙的优势:它可以访问Socketprotected成员,并且可以重写Socket的虚函数(如果有的话)。

更重要的是,对于使用Connection类的人来说,他们完全感知不到Socket的存在Connection就是一个独立的类,它只是"恰好"用Socket来实现自己而已。这完美地封装了实现细节!


总结一下,我的"真香"时刻

所以,回到最初的问题:private继承是不是没用?

绝对不是! 它只是用在了更高级、更底层的设计场景中。

  • 当你想表达"A是B的一种"时 → 用public继承。

  • 当你想表达"A是用B来实现的",并且想隐藏B的接口时 → 可以考虑private继承。

当然,在实际开发中,为了代码的清晰和避免复杂的继承关系,很多时候我们会优先选择"组合"(Composition)而不是private继承。但理解private继承的原理,能让你在看一些优秀的开源库或者设计模式时,不至于"一脸懵"。

希望我的这个心路历程能帮到你!C++的学习之路虽然充满挑战,但每解开一个谜题,那种豁然开朗的感觉,真的太棒了!💪

我们下期再见!👋

相关推荐
zh路西法19 分钟前
【玩转VLA具身智能机械臂】(二):MoveIt2 运动规划——架构、配置与 C++ 上手
c++·机械臂·路径规划·vla·planner·moveit2
深蓝海拓1 小时前
基于QtPy (PySide6) 的PLC-HMI工程项目(十五)后续完善和改进:PLC端数据解析的防粘包、残包、废包、拆包
笔记·学习·plc
小黄蚁1 小时前
LVGL学习笔记(六)
笔记·学习
爱和冰阔落1 小时前
【Linux】Ctrl+C 到底做了什么?从键盘、kill 到 alarm,一次讲清信号的产生
linux·运维·c++·安卓
水饺编程1 小时前
第5章,[Win32 章节] :贝塞尔样条曲线(一)
c语言·c++·windows·visual studio
zyf1044161 小时前
暑期实践日志 Day33:整体复盘核查视频,完善剪辑成果
学习·计算机网络·剪辑·暑期实践·课题任务
01_ice1 小时前
前端学习css
前端·css·学习
程序员打怪兽2 小时前
C++:类与对象,封装,继承,多态,构造/析构,重载/重写
c++
Escalating_xu2 小时前
【C++ STL简介】从六大组件到容器、迭代器与算法协作
java·c++·算法
for_ever_love__3 小时前
PySpark学习: 数据输出
开发语言·python·学习·spark