C++ 公有、保护、私有继承的功能区别详解

在C++中,继承有三种访问限定符:public、protected和private。它们决定了父类成员在子类中的访问权限和对外暴露程度。

核心区别总结表

特性 公有继承 (public) 保护继承 (protected) 私有继承 (private)
父类 public成员在子类中的访问权限 public protected private
父类protected成员在子类中的访问权限 protected protected private
外部代码访问继承的父类成员 可通过子类对象访问父类public成员 不可访问 不可访问
后续派生类访问父类成员 可访问父类public/protected成员 只能访问父类public/protected成员(转为protected) 不可访问父类任何成员

语义含义 “是一个” (is-a) 关系 “是受限制的” 关系 “根据某物实现” (implemented-in-terms-of) 关系
使用频率 最常见(约95%场景) 极少使用 较少使用

详细代码示例

 #include <iostream>
using namespace std;

class Base {
public:
    int publicVar = 10;
    void publicMethod() { cout << "Base public method" << endl; }
    
protected:
    int protectedVar = 20;
    void protectedMethod() { cout << "Base protected method" << endl; }
    
private:
    int privateVar = 30;
    void privateMethod() { cout << "Base private method" << endl; }
};

// ================= 公有继承 (public) =================
class PublicDerived : public Base {
public:
    void accessBaseMembers() {
        publicMethod();       // ✅ 可以访问父类public方法
        protectedMethod();    // ✅ 可以访问父类protected方法
        
        // privateMethod();  // ❌ 不能访问父类private方法
    }
};

// ================= 保护继承 (protected) =================
class ProtectedDerived : protected Base {
public:
    void accessBaseMembers() {
        publicMethod();       // ✅ 可以访问(此时public成员变为protected)
        protectedMethod();    // ✅ 可以访问
        
        // privateMethod();  //  ❌ 不能访问
    }
};

// ================= 私有继承 (private) =================
class PrivateDerived : private Base {
public:
    void accessBaseMembers() {
        publicMethod();       // ✅ 可以访问(此时public成员变为private)
        protectedMethod();    // ✅ 可以访问(此时protected成员变为private)
        
        // privateMethod();  //  ❌ 不能访问
    }
};

// 测试函数
void testAccess() {
    // ----------------- 公有继承测试 -----------------
    PublicDerived pubDer;
    pubDer.publicMethod();   // ✅ 外部可直接调用父类public方法
    // pubDer.protectedMethod(); // ❌ 错误:protected成员外部不可访问
    
    // ----------------- 保护继承测试 -----------------
    ProtectedDerived protDer;
    // protDer.publicMethod();  //  ❌ 错误:继承后public成员变为protected,外部不可访问
    
    // ----------------- 私有继承测试 -----------------
    PrivateDerived privDer;
    // privDer.publicMethod();  // ❌ 错误:继承后public成员变为private,外部不可访问
}

// ================= 多级继承测试 =================
class GrandchildPublic : public PublicDerived {
    void access() {
        publicMethod();      // ✅ 可访问(通过public继承保留)
        protectedMethod();   // ✅ 可访问
    }
};

class GrandchildProtected : public ProtectedDerived {
    void access() {
        publicMethod();      // ✅ 可访问(在ProtectedDerived中变为protected)
        protectedMethod();   // ✅ 可访问
    }
};

class GrandchildPrivate : public PrivateDerived {
    void access() {
        // publicMethod();    //  ❌ 不可访问(在PrivateDerived中变为private)
        // protectedMethod(); //  ❌ 不可访问
    }
};

int main() {
    testAccess();
    return 0;
}

关键点解析

  1. 公有继承 (public):
    • 保持父类原有的访问权限
    • 适用于"is-a"关系(例如:Dog继承自Animal)
    • 父类接口完全暴露给子类用户

  2. 保护继承 (protected):
    • 父类的public成员在子类中变为protected
    • 父类的protected成员保持protected
    • 主要用于限制接口暴露(使用场景极少)

  3. 私有继承 (private):
    • 父类的public和protected成员在子类中都变为private
    • 表示"implemented-in-terms-of"关系(根据某物实现)
    • 通常可用组合(composition)替代

最佳实践建议

  1. 优先使用公有继承:当需要表达"is-a"关系时(约95%的继承场景)
  2. 慎用私有继承:仅在需要重写虚函数或进行空基类优化时考虑
  3. 避免使用保护继承:实际项目中几乎总能用组合或公有继承替代
  4. 使用组合代替继承:当关系是"has-a"而非"is-a"时,优先选择包含对象成员

⚠️重要提示:无论使用何种继承方式,父类的private成员始终不可访问,只能通过父类提供的public/protected接口间接访问。*

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐