Effective C++ 条款39:明智而审慎地使用 private 继承

条款39:明智而审慎地使用 private 继承

private 继承 是一种特殊的继承方式,其主要特点包括:

  1. 无隐式转换:如果类之间的继承关系是 private,编译器不会自动将 derived class 的对象转换为 base class 的对象。
  2. 成员访问权限变化:由 private base class 继承而来的所有成员,在 derived class 中都会变为 private 属性,即使它们在 base class 中是 public 或 protected 的。

复合 (composition) 不同,private 继承还支持特定的优化,如 empty base 最优化 (Empty Base Optimization, EBO)。这是实现轻量级对象的重要技术,尤其在一些性能敏感的程序库开发中。


示例 1:private 继承无隐式转换

class Base {
public:
    void display() const {
        std::cout << "Base display" << std::endl;
    }
};

class Derived : private Base {
public:
    void show() const {
        display(); // Derived 可以访问 Base 的成员
    }
};

int main() {
    Derived d;
    d.show();
    // d.display(); // 错误:Base 的成员在 Derived 中是 private 的
    return 0;
}

在这个例子中,DerivedBase 继承了 display,但客户代码不能直接访问它,因为 private 继承使得 Base 的成员变为 Derived 的私有成员


示例 2:private 继承 vs 复合

复合版本

class Base {
public:
    void display() const {
        std::cout << "Base display" << std::endl;
    }
};

class Derived {
public:
    void show() const {
        base.display(); // 使用复合的 Base 对象
    }

private:
    Base base; // 复合关系
};

private 继承版本

class Base {
public:
    void display() const {
        std::cout << "Base display" << std::endl;
    }
};

class Derived : private Base {
public:
    void show() const {
        display(); // 直接访问 Base 的成员
    }
};

两者的主要区别在于,复合关系 更适合描述 “has-a” 关系,而 private 继承 更适合描述 “is-implemented-in-terms-of” 关系。


示例 3:empty base 最优化 (EBO)

当基类为空时,private 继承可以避免不必要的内存开销。以下示例展示了 EBO 的效果:

class EmptyBase {};

class Derived : private EmptyBase {
public:
    int value;
};

int main() {
    std::cout << "Size of EmptyBase: " << sizeof(EmptyBase) << std::endl;
    std::cout << "Size of Derived: " << sizeof(Derived) << std::endl;
    return 0;
}

在此例中,Derived 类继承自 EmptyBase,但其大小可能与 int 相同。这是因为编译器可以利用 EBO 消除空基类的内存占用。


适用场景

  • 复合优先:如果你只是需要实现某种功能,复合通常是更直观的选择。
  • private 继承:当你需要从基类中继承实现(而非接口),或者需要利用 EBO 最优化内存布局时,可以使用 private 继承。

总结

  • private 继承 适用于描述 “is-implemented-in-terms-of” 关系。
  • 与复合相比,private 继承可以直接访问基类成员,但不能隐式转换为基类类型。
  • 在需要优化对象尺寸时,private 继承可能优于复合,因为它可以触发 EBO
引用 引用 引用根据这些引用内容,警告信息"warning: in the working copy of &#39;androidPrivacy.json&#39;, LF will be replaced by CRLF the next time Git touches it"是在提醒用户在Git操作中,回车和换行的转换将会发生。这是因为Git会在提交时对换行符进行转换以保持统一性。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [warning: in the working copy of ‘App.vue‘, LF will be replaced by CRLF the next time Git touches ...](https://blog.youkuaiyun.com/weixin_44953057/article/details/129644219)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Git: ‘LF will be replaced by CRLF the next time Git touches it‘ 问题解决与思考](https://blog.youkuaiyun.com/Babylonxun/article/details/126598477)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [warning: in the working copy of ‘...‘, LF will be replaced by CRLF the next time Git touche](https://blog.youkuaiyun.com/weixin_55252589/article/details/129017650)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值