MST

星途 面试题库

面试题:C++类访问控制在继承体系下对封装性的复杂影响

在C++的继承体系中,基类的不同访问控制属性(public、private和protected继承)如何影响派生类对基类成员的访问以及整体的封装性?请详细分析每种继承方式下,派生类对象和派生类成员函数对基类成员的访问规则,并举例说明这种访问控制对封装性的具体影响。
18.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

public继承

  1. 派生类成员函数对基类成员的访问
    • 基类的public成员在派生类中仍然是public的,可以被派生类的成员函数直接访问。
    • 基类的protected成员在派生类中仍然是protected的,可以被派生类的成员函数访问。
    • 基类的private成员在派生类中是不可访问的,派生类成员函数无法直接访问基类的private成员。
  2. 派生类对象对基类成员的访问
    • 派生类对象可以访问基类的public成员,但不能访问基类的protected和private成员。
  3. 对封装性的影响:public继承保持了基类的接口特性,派生类对象可以像使用基类对象一样使用基类的public成员,很好地遵循了面向对象的Liskov替换原则,有利于代码的复用和扩展,同时也维护了一定的封装性,因为private和protected成员依然受到保护。
    • 示例
class Base {
public:
    int publicData;
protected:
    int protectedData;
private:
    int privateData;
};

class PublicDerived : public Base {
public:
    void accessBaseMembers() {
        publicData = 1; // 可以访问
        protectedData = 2; // 可以访问
        // privateData = 3; // 编译错误,无法访问
    }
};

int main() {
    PublicDerived pd;
    pd.publicData = 4; // 可以访问
    // pd.protectedData = 5; // 编译错误,无法访问
    // pd.privateData = 6; // 编译错误,无法访问
    return 0;
}

private继承

  1. 派生类成员函数对基类成员的访问
    • 基类的public和protected成员在派生类中都变为private的,可以被派生类的成员函数直接访问。
    • 基类的private成员在派生类中仍然是不可访问的,派生类成员函数无法直接访问基类的private成员。
  2. 派生类对象对基类成员的访问
    • 派生类对象不能访问基类的任何成员(包括原来的public成员,因为在private继承下都变为private了)。
  3. 对封装性的影响:private继承使得基类的所有可访问成员在派生类中变为private,极大地增强了封装性,派生类对象无法直接访问基类的接口,基类的实现细节被更好地隐藏起来,但是也限制了派生类对象对基类接口的使用,代码的复用性相对public继承会降低。
    • 示例
class Base {
public:
    int publicData;
protected:
    int protectedData;
private:
    int privateData;
};

class PrivateDerived : private Base {
public:
    void accessBaseMembers() {
        publicData = 1; // 可以访问,变为private
        protectedData = 2; // 可以访问,变为private
        // privateData = 3; // 编译错误,无法访问
    }
};

int main() {
    PrivateDerived pd;
    // pd.publicData = 4; // 编译错误,无法访问
    // pd.protectedData = 5; // 编译错误,无法访问
    // pd.privateData = 6; // 编译错误,无法访问
    return 0;
}

protected继承

  1. 派生类成员函数对基类成员的访问
    • 基类的public和protected成员在派生类中都变为protected的,可以被派生类的成员函数直接访问。
    • 基类的private成员在派生类中仍然是不可访问的,派生类成员函数无法直接访问基类的private成员。
  2. 派生类对象对基类成员的访问
    • 派生类对象不能访问基类的任何成员(包括原来的public成员,因为在protected继承下都变为protected了)。
  3. 对封装性的影响:protected继承介于public和private继承之间,它保护了基类的接口,使得派生类对象无法访问基类接口,但派生类的派生类(如果有)可以访问基类的public和protected成员(在变为protected的情况下),在一定程度上维护了封装性和代码的扩展性。
    • 示例
class Base {
public:
    int publicData;
protected:
    int protectedData;
private:
    int privateData;
};

class ProtectedDerived : protected Base {
public:
    void accessBaseMembers() {
        publicData = 1; // 可以访问,变为protected
        protectedData = 2; // 可以访问,变为protected
        // privateData = 3; // 编译错误,无法访问
    }
};

int main() {
    ProtectedDerived pd;
    // pd.publicData = 4; // 编译错误,无法访问
    // pd.protectedData = 5; // 编译错误,无法访问
    // pd.privateData = 6; // 编译错误,无法访问
    return 0;
}