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

news2024/12/24 15:32:24

一、概念

        构造函数(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.coloradmin.cn/o/2264792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PSDK的编译与ROS包封装

本文档讲述在NIVIDIA开发板上使用大疆提供的Payload SDK获取无人机实时GPS信息的方法&#xff0c;以及基于Payload SDK发布ROS GPS话题信息的方法。 文章目录 0 实现目标1 Payload SDK1.1 PSDK 源码的编译1.2 PSDK 的使用 2 遥测数据的读取2.1 示例代码结构2.2 读取机载GPS信息…

铝电解电容使用寿命

铝电解电容寿命问题 铝电解电容为什么会失效&#xff1f;铝电解电容失效与那些因素有关&#xff1f;电解电容寿命如何计算&#xff1f; 1铝电解电容为什么会失效&#xff1f; 电容都是由两个导电板并排放到一起就构成了。正极是铝&#xff08;阳极箔&#xff09;&#xff0c;…

用Python PySide6 复刻了两软件UI 做下练习

图样 1 代码 1&#xff1a; # -*- coding: utf-8 -*-import sys from PySide6.QtCore import (QCoreApplication, QMetaObject, QRect, QDate) from PySide6.QtGui import QIcon, QPixmap, QColor from PySide6.QtWidgets import (QApplication, QDialog, QLineEdit, QPushBut…

安装MongoDB,环境配置

官网下载地址&#xff1a;MongoDB Shell Download | MongoDB 选择版本 安装 下载完成双击打开 点击mongodb-windows-x86_64-8.0.0-signed 选择安装地址 检查安装地址 安装成功 二.配置MongoDB数据库环境 1.找到安装好MongoDB的bin路径 复制bin路径 打开此电脑 -> 打开高级…

Spring学习(一)——Sping-XML

一、Spring的概述 (一)什么是Spring? Spring是针对bean对象的生命周期进行管理的轻量级容器。提供了功能强大IOC、AOP及Web MVC等功能。Spring框架主要由七部分组成&#xff1a;分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 S…

重温设计模式--职责链模式

文章目录 职责链模式的详细介绍C 代码示例C示例代码2 职责链模式的详细介绍 定义与概念 职责链模式&#xff08;Chain of Responsibility Pattern&#xff09;是一种行为型设计模式&#xff0c;它旨在将请求的发送者和多个接收者解耦&#xff0c;让多个对象都有机会处理请求&a…

easegen将教材批量生成可控ppt课件方案设计

之前客户提出过一个需求&#xff0c;就是希望可以将一本教材&#xff0c;快速的转换为教学ppt&#xff0c;虽然通过人工程序脚本的方式&#xff0c;已经实现了该功能&#xff0c;但是因为没有做到通用&#xff0c;每次都需要修改脚本&#xff0c;无法让客户自行完成所有流程&am…

高考志愿填报:如何制定合理的志愿梯度?

高考志愿填报中常见的避雷行为&#xff0c;深入分析了专业选择、招生政策了解、学校选择、备选方案准备以及防诈骗等方面的关键问题&#xff0c;并提出了针对性的建议与策略。旨在为考生和家长提供实用的指导&#xff0c;助力考生科学合理地填报高考志愿&#xff0c;避免陷入各…

如何查看vivado项目所使用的版本

在我们提供的各类教程中vivado使用的版本都不同&#xff0c;而使用不同版本的vivado打开项目时可能会产生一些其它错误&#xff0c;所有最好使用对应的vivado版本打开&#xff0c;本例主要演示如何查看项目所示使用的vivado版本。 如下图所示&#xff0c;为vivado2023.1版本创建…

ue5 pcg(程序内容生成)真的简单方便,就5个节点

总结&#xff1a; 前情提示 鼠标单击右键平移节点 1.编辑-》插件-》procedural->勾选两个插件 2.右键-》pcg图表-》拖拽进入场景 3.先看点point 右键-》调试(快捷键d)->右侧设置粒子数 3.1调整粒子数 可以在右侧输入框&#xff0c;使用加减乘除 4.1 表面采样器 …

光谱相机在农业的应用

一、作物生长监测1、营养状况评估 原理&#xff1a;不同的营养元素在植物体内的含量变化会导致植物叶片或其他组织的光谱反射率特性发生改变。例如&#xff0c;氮元素是植物叶绿素的重要组成部分&#xff0c;植物缺氮时&#xff0c;叶绿素含量下降&#xff0c;其在可见光波段&a…

基于Springboot的数字科技风险报告管理系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了多年的设计程序开发&#xff0c;开发过上千套设计程序&#xff0c;没有什么华丽的语言&#xff0c;只有实…

14,攻防世界Web_php_unserialize

进入场景 看见代码&#xff0c;解析一下 这段PHP代码定义了一个名为Demo的类&#xff0c;并演示了如何通过URL参数进行反序列化和文件高亮显示的功能&#xff0c;同时也包含了一些安全措施以防止对象注入攻击。下面是对这段代码的逐行解释&#xff1a; 1.<php 开始PHP代码…

基于NodeMCU的物联网窗帘控制系统设计

最终效果 基于NodeMCU的物联网窗帘控制系统设计 项目介绍 该项目是“物联网实验室监测控制系统设计&#xff08;仿智能家居&#xff09;”项目中的“家电控制设计”中的“窗帘控制”子项目&#xff0c;最前者还包括“物联网设计”、“环境监测设计”、“门禁系统设计计”和“小…

【Linux开发工具】自动化构建-make/Makefile

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;Linux &#x1f339;往期回顾&#x1f339;&#xff1a;【Linux开发工具】gcc和g &#x1f516;流水不争&#xff0c;争的是滔滔不 一、make和Makefile简介1.1 什么是…

Elasticsearch安装和数据迁移

Elasticsearch安装和数据迁移 Elasticsearch安装 下载并解压Elasticsearch 首先下载Elasticsearch的tar.gz文件&#xff0c;并将其解压&#xff1a; wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.8.2-linux-x86_64.tar.gz tar -xzf elastics…

dockerfile文档编写(1):基础命令

目录 Modelscope-agentARGFROMWORKDIRCOPYRUNENVCMD run_loopy Modelscope-agent ARG BASE_IMAGEregistry.cn-beijing.aliyuncs.com/modelscope-repo/modelscope:ubuntu22.04-cuda12.1.0-py310-torch2.1.2-tf2.14.0-1.12.0FROM $BASE_IMAGEWORKDIR /home/workspaceCOPY . /hom…

【论文阅读笔记】Learning to sample

Learning to sample 前沿引言方法问题声明S-NET匹配ProgressiveNet: sampling as ordering 实验分类检索重建 结论附录 前沿 这是一篇比较经典的基于深度学习的点云下采样方法 核心创新点&#xff1a; 首次提出了一种学习驱动的、任务特定的点云采样方法引入了两种采样网络&…

置换密码程序设计

实验目的与要求 1. 帮助学生掌握置换密码的加密解密过程&#xff0c;能够利用所学过的编程语言&#xff0c;实现加解密算法。使学生掌握编程实现实际问题中的方法&#xff0c;提高专业技能和专业素养。 2. 要求学生掌握算法的程序实现的方法,能应用密码算法的特点&#xff0c…

Android修行手册 - 移动端几种常用动画方案对比

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…