面试题答案
一键面试构造函数和析构函数重载限制对对象创建和销毁的影响
-
构造函数重载:
- 构造函数可以重载,这意味着在类中可以定义多个构造函数,它们具有不同的参数列表。这为对象的创建提供了灵活性。例如,在
Base
类中,可以定义一个默认构造函数和一个带参数的构造函数。 - 当创建派生类对象时,派生类的构造函数首先会调用基类的构造函数。如果基类没有默认构造函数,派生类构造函数必须在初始化列表中显式调用基类的合适构造函数。
- 构造函数可以重载,这意味着在类中可以定义多个构造函数,它们具有不同的参数列表。这为对象的创建提供了灵活性。例如,在
-
析构函数重载:
- 析构函数不能重载,每个类只能有一个析构函数。析构函数在对象销毁时自动调用,负责释放对象所占用的资源。
- 当派生类对象被销毁时,首先调用派生类的析构函数,然后调用基类的析构函数。
多重继承对构造函数和析构函数的影响
- 构造函数:
- 在多重继承中,派生类会继承多个基类。派生类的构造函数需要在初始化列表中依次调用每个基类的构造函数。调用顺序与继承列表中基类的顺序一致。
- 例如,假设有
Derived
类继承自Base1
和Base2
:
class Base1 {
public:
Base1() { std::cout << "Base1 constructor" << std::endl; }
~Base1() { std::cout << "Base1 destructor" << std::endl; }
};
class Base2 {
public:
Base2() { std::cout << "Base2 constructor" << std::endl; }
~Base2() { std::cout << "Base2 destructor" << std::endl; }
};
class Derived : public Base1, public Base2 {
public:
Derived() { std::cout << "Derived constructor" << std::endl; }
~Derived() { std::cout << "Derived destructor" << std::endl; }
};
- 在
Derived
类的构造函数中,会先调用Base1
的构造函数,再调用Base2
的构造函数,最后执行Derived
类自身的构造函数代码。
- 析构函数:
- 析构函数的调用顺序与构造函数相反。在
Derived
类对象销毁时,首先调用Derived
类的析构函数,然后依次调用Base2
和Base1
的析构函数。
- 析构函数的调用顺序与构造函数相反。在
虚继承对构造函数和析构函数的影响
- 构造函数:
- 虚继承用于解决多重继承中的菱形继承问题,避免数据冗余和歧义。在虚继承中,最底层的派生类负责初始化虚基类。
- 例如:
class VirtualBase {
public:
VirtualBase() { std::cout << "VirtualBase constructor" << std::endl; }
~VirtualBase() { std::cout << "VirtualBase destructor" << std::endl; }
};
class Base3 : virtual public VirtualBase {
public:
Base3() { std::cout << "Base3 constructor" << std::endl; }
~Base3() { std::cout << "Base3 destructor" << std::endl; }
};
class Base4 : virtual public VirtualBase {
public:
Base4() { std::cout << "Base4 constructor" << std::endl; }
~Base4() { std::cout << "Base4 destructor" << std::endl; }
};
class FinalDerived : public Base3, public Base4 {
public:
FinalDerived() { std::cout << "FinalDerived constructor" << std::endl; }
~FinalDerived() { std::cout << "FinalDerived destructor" << std::endl; }
};
- 在
FinalDerived
类的构造函数中,虽然Base3
和Base4
都虚继承自VirtualBase
,但只有FinalDerived
类负责调用VirtualBase
的构造函数。
- 析构函数:
- 析构函数的调用顺序同样与构造函数相反。
FinalDerived
类的析构函数先执行,然后依次调用Base4
、Base3
和VirtualBase
的析构函数。
- 析构函数的调用顺序同样与构造函数相反。
通过上述分析和代码示例,可以清晰地看到构造函数和析构函数重载限制以及多重继承、虚继承对对象创建和销毁过程的影响。