MST

星途 面试题库

面试题:C++中构造函数非虚特性在继承体系中的体现

请描述在C++继承体系中,构造函数的非虚特性是如何影响对象的创建过程的?举例说明,并解释为什么构造函数不能是虚函数。
31.7万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试
  1. 构造函数非虚特性对对象创建过程的影响
    • 在C++继承体系中,构造函数是非虚的。这意味着在创建对象时,编译器根据对象的静态类型确定调用哪个构造函数。
    • 当创建派生类对象时,首先调用基类构造函数,然后调用派生类构造函数。这个顺序是固定的,与指针或引用的动态类型无关。例如:
class Base {
public:
    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”。这是因为编译器根据Derived的静态类型,知道要先构造基类部分,再构造派生类部分。如果构造函数是虚函数,就无法确定先调用哪个构造函数,因为虚函数的调用依赖于对象的动态类型,而在对象构造期间,对象的动态类型是不完整的。
  1. 举例说明
class A {
public:
    A() {
        std::cout << "A constructor" << std::endl;
    }
};

class B : public A {
public:
    B() {
        std::cout << "B constructor" << std::endl;
    }
};

class C : public B {
public:
    C() {
        std::cout << "C constructor" << std::endl;
    }
};

int main() {
    C c;
    return 0;
}
  • 输出结果为:
A constructor
B constructor
C constructor
  • 这清晰地展示了构造函数按照继承层次从基类到派生类依次调用,不受虚函数机制影响。
  1. 为什么构造函数不能是虚函数
    • 对象创建的顺序问题:如前面所述,构造函数需要按照继承层次依次调用,从基类到派生类。虚函数依赖于虚函数表指针(vptr),而vptr是在对象构造过程中才被初始化的。如果构造函数是虚函数,在调用构造函数时vptr还未初始化,就无法实现虚函数的动态绑定机制。
    • 对象的不完整性:在构造函数执行期间,对象处于不完整状态。虚函数机制依赖于完整的对象状态来确定动态类型,而构造函数正在创建对象,此时对象的动态类型还未完全确定,所以构造函数不能是虚函数。