MST

星途 面试题库

面试题:C++继承方式与多态性的关联

在C++中,不同的继承方式(public、private、protected)对多态性的实现有什么影响?请从虚函数、函数重写以及对象切片等方面进行分析,并给出具体代码示例说明。
24.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 继承方式对多态性相关概念的影响

虚函数

  • public继承:在public继承下,基类的虚函数在派生类中仍然保持虚函数的性质。这意味着派生类可以重写(override)这些虚函数,以实现多态行为。
  • private继承:基类的虚函数在private继承的派生类中变为private成员函数。虽然派生类内部可以重写这些函数,但对于外部代码,无法通过基类指针或引用调用派生类重写的虚函数,多态性无法在类外部体现。
  • protected继承:基类的虚函数在protected继承的派生类中变为protected成员函数。与private继承类似,外部代码无法通过基类指针或引用调用派生类重写的虚函数,多态性在类外部受限。

函数重写

  • public继承:派生类通过重写基类的虚函数来实现多态。重写的函数需要满足函数签名(参数列表和返回类型)与基类虚函数一致(协变返回类型除外)。通过基类指针或引用调用虚函数时,会根据对象的实际类型调用相应派生类的重写函数。
  • private继承:尽管派生类可以重写基类虚函数,但由于访问权限问题,外部代码无法通过基类指针或引用访问到派生类重写的函数,不能实现多态调用。
  • protected继承:同样,派生类可重写基类虚函数,但外部代码不能通过基类指针或引用调用派生类重写的函数,多态性受限。

对象切片

  • public继承:对象切片发生在将派生类对象赋值给基类对象时,会丢失派生类特有的部分数据。在多态调用中,如果通过值传递(而非指针或引用),对象切片会导致调用的是基类版本的虚函数,破坏多态性。
  • private和protected继承:由于外部代码无法直接访问派生类对象(通过基类接口),对象切片的场景在这些继承方式下对于外部代码来说不太容易出现,但在类内部或友元函数中仍可能发生类似行为,同样可能影响多态性。

2. 代码示例

#include <iostream>

class Base {
public:
    virtual void print() {
        std::cout << "Base::print()" << std::endl;
    }
};

// public继承
class PublicDerived : public Base {
public:
    void print() override {
        std::cout << "PublicDerived::print()" << std::endl;
    }
};

// private继承
class PrivateDerived : private Base {
public:
    void print() {
        std::cout << "PrivateDerived::print()" << std::endl;
    }
};

// protected继承
class ProtectedDerived : protected Base {
public:
    void print() {
        std::cout << "ProtectedDerived::print()" << std::endl;
    }
};

int main() {
    // public继承多态测试
    Base* publicPtr = new PublicDerived();
    publicPtr->print(); // 输出 PublicDerived::print()
    delete publicPtr;

    // private继承测试
    PrivateDerived privateObj;
    // Base* privatePtr = &privateObj; // 错误,无法从PrivateDerived* 转换为 Base*
    // privatePtr->print(); // 无法通过此方式调用

    // protected继承测试
    ProtectedDerived protectedObj;
    // Base* protectedPtr = &protectedObj; // 错误,无法从ProtectedDerived* 转换为 Base*
    // protectedPtr->print(); // 无法通过此方式调用

    return 0;
}

在上述代码中,PublicDerived 通过 public 继承 Base,可以实现多态调用 print 函数。而 PrivateDerivedProtectedDerived 分别通过 privateprotected 继承 Base,外部代码无法通过 Base 指针或引用调用它们重写的 print 函数,多态性受到限制。