当前位置: 首页 > news >正文

[C++面试] 基础题 11~20

11、为什么构造函数可以重载,析构函数不可以?

构造函数用于对象的创建,不同场景可能需要不同的初始化参数。

class MyClass {
public:MyClass() { /* 默认初始化 */ }          // 无参构造函数MyClass(int x) { /* 用x初始化 */ }      // 单参数构造函数MyClass(int x, double y) { /* 复杂初始化 */ } // 双参数构造函数
};

        语法上:构造函数与类名相同且无返回值,但允许参数列表不同。 


C++标准规定析构函数必须无参数且唯一。

析构函数在对象销毁时由编译器自动调用,且无参数。若允许重载,编译器无法确定应调用哪个版本。析构函数的核心职责是释放资源​(如内存、文件句柄等),通常需要统一的清理逻辑。若需差异化处理,应通过成员变量状态控制,而非重载

class FileHandler {
private:bool isOpen = false;
public:~FileHandler() {if (isOpen) fclose(filePtr); // 根据状态统一处理}
};

12、 构造函数可以是虚函数吗?为什么?

对象尚未完全构造

虚函数的调用通过对象的虚指针(vptr)和虚表(vtable)实现动态绑定。

在构造函数执行时,对象的虚指针尚未初始化(仅在基类构造函数完成后才指向派生类的虚表)。

设计逻辑冲突

构造函数从基类到派生类依次执行。

若基类构造为虚函数,派生类可能会尝试调用自身版本的构造函数(此时派生类对象尚未完全构造),导致逻辑混乱。

语言规范限制

C++标准明确规定构造函数不能声明为virtual,编译器会直接报错

13、 析构函数何时必须是虚函数?为什么?

必须声明为虚函数的场景:通过基类指针删除派生类对象时

class Base {
public:virtual ~Base() { cout << "Base destructor" << endl; } // 虚析构函数
};class Derived : public Base {
private:int* data;
public:Derived() { data = new int[10]; }~Derived() override {delete[] data; // 派生类资源清理cout << "Derived destructor" << endl;}
};// 使用基类指针创建和删除派生类对象
Base* ptr = new Derived();
delete ptr; // 若Base析构非虚,则仅调用Base::~Base(),导致Derived::data未释放

声明基类析构函数为虚函数后,delete 基类指针时会先调用派生类析构函数,再调用基类析构函数,保证资源被完整释放。 

14、默认构造函数与无参构造函数

默认构造函数是指无需参数即可调用的构造函数。包括:

  • 编译器自动生成的构造函数:当类中未定义任何构造函数时,编译器隐式生成一个无参构造函数(称为 “合成默认构造函数”)。
  • 用户显式定义的无参构造函数:如 Data() {} 或 Data() = default
// 若类中定义了任何构造函数(无论是否带参数),编译器不会自动生成默认构造函数。因此,以下两种情况都会导致默认构造函数缺失
struct Data1 {Data1(int x) {}  // 带参构造函数 → 无默认构造函数
};struct Data2 {Data2() {}  // 用户显式定义无参构造函数 → 编译器不再生成默认构造函数
};

默认构造函数是编译器自动生成或用户显式定义的无参数构造函数,或者所有参数均有默认值的构造函数(如 MyClass(int x = 0))。其核心特点是无需传递参数即可调用。 

class MyClass {
public:MyClass(int x = 0, double y = 1.0) { /* 参数均有默认值 */ }
};
// 此时,MyClass obj; 或 MyClass obj{}; 均可调用该构造函数

无参构造函数(Parameterless Constructor)

无参构造函数是参数列表为空的构造函数,属于默认构造函数的一种特例。

  • 用户显式定义的、参数列表为空的构造函数。(如 MyClass() {}
  • 用户未定义任何构造函数时,编译器自动生成隐式无参构造函数
  • 必须由用户手动编写,编译器不会自动生成(除非使用= default

默认构造函数是一个更宽泛的概念,包括编译器生成的和用户定义的无参构造函数。


默认构造函数的显式声明方式

方式 1:用户自定义无参构造函数

class MyClass {
public:MyClass() {  // 自定义默认构造函数// 初始化逻辑}
};

方式 2:使用= default强制编译器生成 

class MyClass {
public:MyClass() = default;  // 显式要求编译器生成默认构造函数
};

当类定义了任何构造函数(包括无参构造函数)时,编译器不会自动生成默认构造函数

可通过= default显式请求。

class Data {
public:Data(int val) : value(val) {}  // 定义带参构造函数Data() = default;  // 显式生成默认构造函数
private:int value;
};

派生类的构造函数会隐式调用基类的默认构造函数。若基类无默认构造函数,派生类必须显式调用基类的其他构造函数。 

class Base {
public:Base(int x) {}  // 基类无默认构造函数
};class Derived : public Base {
public:Derived() : Base(0) {}  // 必须显式调用Base的构造函数
};

聚合类(无用户声明构造函数、无私有 / 保护成员、无虚函数)可使用聚合初始化(花括号语法),即使没有默认构造函数。 

struct Data {int x;Data(int x) : x(x) {}  // 有带参构造函数,无默认构造函数
};
Data d{42};  // 合法:聚合初始化
Data d;      // 非法:无默认构造函数

工程中的最佳实践:

  • 若类需要默认初始化,即使为空,也显式声明
  • 使用成员初始化器确保所有成员被正确初始化,避免基本类型未初始化
  • 设计类接口时考虑默认构造的必要性
  • 若类不允许无参初始化,显式删除默认构造函数
  • const 和引用成员:必须通过构造函数初始化列表初始化,隐式默认构造函数无法处理
class ConstDemo {
public:const int c;ConstDemo() : c(10) {} // 必须显式初始化
};

在C++中,​每个类最多只能有一个默认构造函数,即以下两种形式不能同时存在:

  1. 无参构造函数​(无参数)
  2. 全缺省参数构造函数​(所有参数均有默认值)

若同时定义这两种形式,会导致编译错误

class Date {
public:// 无参构造函数Date() : _year(1), _month(1), _day(1) {}  // 默认构造函数①// 全缺省参数构造函数(等价于默认构造函数②)Date(int year = 1, int month = 1, int day = 1) : _year(year), _month(month), _day(day) {}
private:int _year, _month, _day;
};int main() {Date d1;  // 错误:存在多个默认构造函数return 0;
}

 

相关文章:

  • 归一化 超全总结!!
  • 编译rk3568的buildroot不起作用
  • pvlib(太阳轨迹)
  • 基于CodeBuddy实现本地网速的实时浏览小工具
  • 算法题(154):合并果子
  • [NOIP 2003 普及组] 麦森数 Java
  • 由浮点数的位级表示判断大小关系
  • 电子电路:为什么导体中的电子数量能够始终保持不变?
  • VBA 读取指定范围内的单元格数据,生成csv文件
  • [软件测试_5] 设计用例 | 等价法 | 判定表法 | 正交法(allpairs.exe)
  • Compose 中的 LaunchedEffect
  • 基于大模型预测的视神经脊髓炎技术方案
  • CAU人工智能class6 ResNet
  • vocabulary in program
  • Swagger
  • 头歌软工导论作业
  • 深度学习模型在PDE求解中的实战:详细综述
  • Ntfs!ReadIndexBuffer函数分析之根目录读取索引缓冲区的一个例子
  • 给定终点和时间的DoubleS轨迹
  • 51页 @《人工智能生命体 新启点》中國龍 原创连载
  • 网站的小图标怎么做的/河南网站seo推广
  • 成都html5网站建设/短视频seo关键词
  • 石家庄企业如何建网站/app运营
  • 武汉值得去的互联网公司/北京快速优化排名
  • 如何在网站上做免费广告/百度热搜榜在哪里看
  • 嘉善网站建设/免费网站申请域名