深入理解构造函数:C++ 编程中的基石

news/2024/12/24 6:23:05/

一、概念

        构造函数(Constructor) 是一种特殊的成员函数,用于在创建对象时初始化对象的状态(即成员变量)。它的主要作用是保证对象在创建时具有有效的初始值。


二、特点

与类同名

  • 构造函数的名称与类名相同,没有返回值(甚至不能写 void)。

自动调用

  • 构造函数在对象创建时自动调用,无需显式调用。

可以重载

  • 构造函数可以有多个版本,依赖于参数个数和类型(重载)。

无返回值

  • 构造函数没有返回值,也不能通过返回值来传递信息。

默认构造函数

  • 如果用户没有定义构造函数,编译器会自动生成一个无参的默认构造函数。
  • 如果用户定义了任何构造函数,编译器将不再生成默认构造函数。

三、种类

1. 默认构造函数

无参数的构造函数,称为默认构造函数。

  • 作用:初始化对象为默认状态。
  • 示例:
class Example {
public:Example() {  // 默认构造函数cout << "Default constructor called" << endl;}
};int main() {Example obj;  // 自动调用默认构造函数return 0;
}

2. 带参数的构造函数

构造函数可以带参数,用于初始化对象时传递参数。

  • 示例:
class Example {
private:int value;
public:Example(int v) {  // 带参数的构造函数value = v;cout << "Constructor called with value: " << value << endl;}
};int main() {Example obj(10);  // 调用带参数的构造函数return 0;
}

3. 拷贝构造函数

拷贝构造函数用于创建一个对象时,以另一个同类型的对象对其初始化。

  • 特点:参数是同类的引用类型,通常形式为 ClassName(const ClassName &obj)
  • 示例:
class Example {
private:int value;
public:Example(int v) {value = v;cout << "Parameterized constructor called" << endl;}Example(const Example &obj) {  // 拷贝构造函数value = obj.value;cout << "Copy constructor called" << endl;}
};int main() {Example obj1(10);         // 调用带参数的构造函数Example obj2 = obj1;      // 调用拷贝构造函数return 0;
}

4. 委托构造函数

一个构造函数可以调用另一个构造函数来简化代码逻辑。

  • 示例:
class Example {
private:int value;
public:Example() : Example(0) {  // 调用另一个构造函数cout << "Default constructor called" << endl;}Example(int v) {value = v;cout << "Parameterized constructor called with value: " << value << endl;}
};int main() {Example obj;   // 调用默认构造函数,同时委托到带参数的构造函数return 0;
}

5. 默认和删除的构造函数

  • 可以显式指定构造函数为默认的或删除的(C++11 引入)。
  • 示例:
class Example {
public:Example() = default;  // 默认构造函数Example(int) = delete;  // 禁止使用此构造函数
};int main() {Example obj1;     // 可以// Example obj2(10);  // 错误,无法使用删除的构造函数return 0;
}

四、构造函数的使用与初始化列表

初始化成员变量

可以在构造函数中直接初始化成员变量,或使用 初始化列表 初始化。

  • 示例:
class Example {
private:int a;int b;
public:Example(int x, int y) : a(x), b(y) {  // 初始化列表cout << "a = " << a << ", b = " << b << endl;}
};int main() {Example obj(10, 20);  // 调用构造函数return 0;
}

初始化列表

  • 初始化列表在对象构造时直接赋值,而不是先默认构造后再赋值,因此效率更高。
  • 某些情况必须使用初始化列表,例如常量成员变量或引用类型。

五、子类构造函数

工作流程

  1. 创建子类对象时,必须先调用父类的构造函数。
  2. 如果子类的构造函数没有显式调用父类的构造函数,则会默认调用父类的无参构造函数。
  3. 如果父类没有无参构造函数,子类必须显式调用父类的某个构造函数。

示例:

#include <iostream>
using namespace std;class Parent {
public:Parent(int x) {cout << "Parent constructor called with value: " << x << endl;}
};class Child : public Parent {
public:Child(int x) : Parent(x) {  // 显式调用父类的构造函数cout << "Child constructor called" << endl;}
};int main() {Child obj(10);  // 调用子类构造函数return 0;
}

输出:

Parent constructor called with value: 10
Child constructor called

六、构造函数的注意点

没有返回值: 构造函数没有返回值,不能使用 return 返回值。

拷贝构造函数的深拷贝与浅拷贝: 如果类中有指针类型成员变量,拷贝构造函数默认执行浅拷贝,这可能会导致资源冲突,建议实现深拷贝。

静态成员的初始化: 静态成员变量需要在类外初始化,不能通过构造函数初始化。

继承中的构造函数:父类的构造函数不会被子类继承,但可以通过子类构造函数显式调用。


构造函数与析构函数的关系

  • 析构函数与构造函数相反,用于对象销毁时释放资源。
  • 析构函数在子类对象销毁时按照从子类到父类的顺序调用。

示例:

#include <iostream>
using namespace std;class Parent {
public:Parent() { cout << "Parent constructor called" << endl; }~Parent() { cout << "Parent destructor called" << endl; }
};class Child : public Parent {
public:Child() { cout << "Child constructor called" << endl; }~Child() { cout << "Child destructor called" << endl; }
};int main() {Child obj;  // 创建子类对象return 0;
}

输出:

Parent constructor called
Child constructor called
Child destructor called
Parent destructor called

七、总结

  1. 构造函数是初始化对象的入口,可以重载。
  2. 带参数构造函数和拷贝构造函数提供了灵活的初始化方式。
  3. 初始化列表是高效的初始化方式,尤其适合常量或引用类型。
  4. 父类的构造函数必须在子类构造函数中显式调用(如果没有无参构造函数)。
  5. 析构函数与构造函数互补,用于释放资源。

http://www.ppmy.cn/news/1557663.html

相关文章

【Cadence射频仿真学习笔记】IC设计中电感的分析、建模与绘制(EMX电磁仿真,RFIC-GPT生成无源器件及与cadence的交互)

一、理论讲解 1. 电感设计的两个角度 电感的设计可以从两个角度考虑&#xff0c;一个是外部特性&#xff0c;一个是内部特性。外部特性就是把电感视为一个黑盒子&#xff0c;带有两个端子&#xff0c;如果带有抽头的电感就有三个端子&#xff0c;需要去考虑其电感值、Q值和自…

机器视觉检测相机基础知识 | 颜色 | 光源 | 镜头 | 分辨率 / 精度 / 公差

注&#xff1a;本文为 “keyence 视觉沙龙中机器视觉检测基础知识” 文章合辑。 机器视觉检测基础知识&#xff08;一&#xff09;颜色篇 视觉检测硬件构成的基本部分包括&#xff1a;处理器、相机、镜头、光源。 其中&#xff0c;和光源相关的最重要的两个参数就是光源颜色和…

Python 异步协程:从 async/await 到 asyncio 再到 async with

在 Python 3.8 以后的版本中&#xff0c;异步编程变得越来越重要。本文将系统介绍 Python 标准库中的异步编程工具&#xff0c;带领大家掌握 async/await 语法和 asyncio 的使用。 从一个简单的场景开始 假设我们在处理一些耗时的 I/O 操作&#xff0c;比如读取多个文件或处理…

基于cobra开发的k8s命令行管理工具k8s-manager

基于cobra开发的k8s命令行管理工具k8s-manager 如果觉得好用&#xff0c;麻烦给个Star!通用配置1 node 分析所有node的资源情况2 analysis 分析Node节点上的资源使用构成3 image 获取指定namespace的所有镜像地址4 resource 获取指定namespace的所有limit 与 Requests大小5 top…

BERT模型入门(1)BERT的基本概念

文章目录 BERT是Bidirectional Encoder Representations from Transformers的首字母简写&#xff0c;中文意思是&#xff1a;Transformer的双向编码器表示。它是谷歌发布的最先进的嵌入模型。BERT在许多NLP任务中提供了更好的结果&#xff0c;如问答、文本生成、句子分类等&…

01.02、判定是否互为字符重排

01.02、[简单] 判定是否互为字符重排 1、题目描述 给定两个由小写字母组成的字符串 s1 和 s2&#xff0c;请编写一个程序&#xff0c;确定其中一个字符串的字符重新排列后&#xff0c;能否变成另一个字符串。 在这道题中&#xff0c;我们的任务是判断两个字符串 s1 和 s2 是…

《类和对象:基础原理全解析(上篇)》

目录 一、浅谈面向过程和面向对象二、C 中的结构体&#xff08;struct&#xff09;1. C 中 struct 的使用 三、C 中的类&#xff08;class&#xff09;四、类的封装性1. 类成员的权限控制关键字2. 权限控制关键字的使用 五、类的六大默认成员函数介绍六、构造函数1. 使用构造函…

go基本知识与语法入门

Go 语言&#xff08;又称 Golang&#xff09;是一种由 Google 开发的开源编程语言&#xff0c;设计目标是简洁、高效、并发友好&#xff0c;适合用于构建高性能的系统和网络应用程序。Go 语言的语法相对简单&#xff0c;非常适合大规模软件开发。 1. 基本结构 Go 程序的基本结…