- 构造函数非虚特性对对象创建过程的影响
- 在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
的静态类型,知道要先构造基类部分,再构造派生类部分。如果构造函数是虚函数,就无法确定先调用哪个构造函数,因为虚函数的调用依赖于对象的动态类型,而在对象构造期间,对象的动态类型是不完整的。
- 举例说明
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
- 这清晰地展示了构造函数按照继承层次从基类到派生类依次调用,不受虚函数机制影响。
- 为什么构造函数不能是虚函数
- 对象创建的顺序问题:如前面所述,构造函数需要按照继承层次依次调用,从基类到派生类。虚函数依赖于虚函数表指针(vptr),而vptr是在对象构造过程中才被初始化的。如果构造函数是虚函数,在调用构造函数时vptr还未初始化,就无法实现虚函数的动态绑定机制。
- 对象的不完整性:在构造函数执行期间,对象处于不完整状态。虚函数机制依赖于完整的对象状态来确定动态类型,而构造函数正在创建对象,此时对象的动态类型还未完全确定,所以构造函数不能是虚函数。