MST

星途 面试题库

面试题:C++ 构造函数与普通函数在多态性表现上的区别

在 C++ 中,多态是一个重要特性。请详细分析构造函数与普通函数在多态性方面的表现有何不同,包括虚函数机制在两者上的应用差异,结合代码示例解释原因。
44.4万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

1. 构造函数与多态性

  • 构造函数不能是虚函数
    • 在 C++ 中,构造函数不能声明为虚函数。原因在于,虚函数的调用依赖于虚函数表指针(vptr),而这个指针是在对象构造过程中被初始化的。在构造函数执行时,对象还未完全构建好,虚函数表指针尚未正确初始化,所以无法实现基于虚函数表的多态调用。
    • 例如:
class Base {
public:
    // 这里尝试将构造函数声明为虚函数是错误的,会导致编译错误
    // virtual Base() {}
    Base() {
        std::cout << "Base constructor" << std::endl;
    }
};

class Derived : public Base {
public:
    Derived() {
        std::cout << "Derived constructor" << std::endl;
    }
};
  • 构造函数调用顺序与多态无关
    • 在创建派生类对象时,首先调用基类构造函数,然后调用派生类构造函数。这个调用顺序是固定的,不依赖于对象的实际类型,不会体现多态性。比如:
Derived d;
// 输出:
// Base constructor
// Derived constructor

2. 普通函数与多态性

  • 普通函数默认非多态
    • 普通成员函数如果不声明为虚函数,调用时根据对象的静态类型决定。例如:
class Base {
public:
    void nonVirtualFunc() {
        std::cout << "Base::nonVirtualFunc" << std::endl;
    }
};

class Derived : public Base {
public:
    void nonVirtualFunc() {
        std::cout << "Derived::nonVirtualFunc" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    basePtr->nonVirtualFunc(); // 输出:Base::nonVirtualFunc
    delete basePtr;
    return 0;
}
  • 虚函数实现多态
    • 当普通成员函数声明为虚函数时,会根据对象的动态类型(实际指向的对象类型)来决定调用哪个函数版本,实现多态。例如:
class Base {
public:
    virtual void virtualFunc() {
        std::cout << "Base::virtualFunc" << std::endl;
    }
};

class Derived : public Base {
public:
    void virtualFunc() override {
        std::cout << "Derived::virtualFunc" << std::endl;
    }
};

int main() {
    Base* basePtr = new Derived();
    basePtr->virtualFunc(); // 输出:Derived::virtualFunc
    delete basePtr;
    return 0;
}

在上述代码中,通过将 virtualFunc 声明为虚函数,basePtr 虽然是 Base* 类型,但实际指向 Derived 对象,调用 virtualFunc 时会调用 Derived 类中的版本,体现了多态性。而普通非虚函数 nonVirtualFunc 则根据指针的静态类型(Base*)调用 Base 类中的版本。