C++ ——构造函数

embedded/2025/2/21 2:54:54/

1、作用:创建对象时,给对象的属性进行初始化

2、特点

        (1)构造函数与类同名

        (2)如果没有显式给出构造函数,编译器会给出默认的构造函数(参数为空,并且函数体也为空);如果给出任意的构造函数,系统默认的构造函数就不存在了

        (3)有返回值,但是不写返回值类型,也不可以写void

        (4)构造函数是在创建对象时自动调用

3、构造函数支持函数重载

4、构造函数也支持函数默认值

1、无参构造函数

编译器默认的构造函数:

    类名(){
   }
#include <iostream>
using namespace std;
class Phone{
private:  
    string brand;  //品牌
    string color;  //颜色
    double price;  //价格
public:
    void play_music() {
        cout<<"播放音乐"<<endl;
    }
    void play_video(){
        cout<<"播放视频"<<endl;
    }
    //无参构造函数
    Phone(){
        cout<<"构造函数"<<endl;
    }
};
int main(){
    //无参构造函数
    Phone p1;
    return 0;
}

2、有参构造函数

#include <iostream>
using namespace std;
class Phone{
private: 
    string brand;  //品牌
    string color;  //颜色
    double price;  //价格
public:
    void play_music() {
        cout<<"播放音乐"<<endl;
    }
    void play_video(){
        cout<<"播放视频"<<endl;
    }
    //有参构造函数
    Phone(string a,string b,double c=2995){
        brand=a;
        color=b;
        price=c;
    }
};
int main(){
    //有参构造函数栈内存对象
    Phone p2("vivo","红",9);
    //有参构造函数堆内存对象
    Phone*p3=new Phone("oppo","蓝",4);
    delete p3;
    p3=NULL;
    return 0;
}

3、构造初始化列表

构造初始化列表:就是构造函数的一种简便写法

注意:构造初始化列表与构造函数不能同时出现

#include <iostream>
using namespace std;
class Person{
private: 
    int id;
    string name;
    string sex;
    bool flag;
public:
    //构造初始化列表
    Person(int id,string name,string sex,bool flag)
        :id(id),name(name),sex(sex),flag(flag){}
    void show(){
        cout<<id<<name<<sex<<endl;
    }
};
 
int main(){
    Person p1(1001,"张三","男",true);
    p1.show();
    return 0;
}

4、拷贝构造函数

作用:用于实现对象的拷贝创建 

特点:

        (1)拷贝构造函数与构造函数构成重载(拷贝构造函数也是与类同名)

        (2)如果不给出拷贝构造函数,编译器会给出默认的拷贝构造函数,完成对象之间的值复制;如果给出拷贝构造函数,编译器就不会提供默认的拷贝构造函数

        (3)拷贝构造函数的参数类型是对象的引用或者是const修饰的对象的引用

        (4)拷贝构造函数是在拷贝创建对象时自动调用

注意:对象之间是相互独立的,对象之间的属性也是相互独立的

4.1 浅拷贝 

编译器默认给出的拷贝构造函数,完成的就是浅拷贝,会完成对象之间简单的值复制 

#include <iostream>
using namespace std;
class Person{
private:  
    int id;
    string name;
    string sex;
    bool flag;
public:
    //构造初始化列表
    Person(int id,string name,string sex,bool flag)
        :id(id),name(name),sex(sex),flag(flag){}
    //编译器给出的默认的拷贝构造函数(手写出来的)----->浅拷贝 
    Person(const Person&p){
        id=p.id;
        name=p.name;
        sex=p.sex;
        flag=p.flag;
    }
    void show(){
        cout<<id<<name<<sex<<endl;
    }
};
int main(){
    Person p1(1001,"张三","男",true);  //调用有参的构造函数
    p1.show();
//    //方法一:
//    Person&pp=p1;
//    Person p2(pp);
    //方法二:
    Person p2(p1);  //调用拷贝构造函数
    p2.show();
    return 0;
}

默认拷贝构造函数存在安全隐患:如果成员变量是指针类型,两个对象的指针类型属性指向同一个内存空间,破坏了对象的独立性,那么这种拷贝叫浅拷贝 

解决方法:使用深拷贝

4.2 深拷贝

实现方式:创建对象时,指针属性要有自己独立的区域;拷贝对象时,由地址拷贝变成内容拷贝

#include <iostream>
#include <string.h>
using namespace std;
class Animal{
private:
    string kind;  //种类
    double weight;  //体重
    char*hobby;  //爱好
public:
    //构造函数---->深拷贝
    Animal(string k,double w,char*h){
        kind=k;
        weight=w;
        //创建对象时,指针属性要有自己独立的区域
        hobby=new char[20];
        strcpy(hobby,h);  //使用strcpy前,需要引入string.h头文件
    }
    //展示信息
    void show(){
        cout<<"种类:"<<kind<<",体重:"<<weight<<",爱好:"<<hobby<<endl;
    }
    //kind读接口
    string get_kind(){
        return kind;
    }
    //拷贝构造函数---->深拷贝
    Animal(const Animal&c){
        kind=c.kind;
        weight=c.weight;
        //拷贝对象时,由地址拷贝变成内容拷贝
        hobby=new char[20];
        strcpy(hobby,c.hobby);
    }
};
int main(){
    char h[20]="eat fish";
    Animal cat1("小猫",12,h);  //调用有参构造函数
    cat1.show();
    Animal cat2(cat1);  //调用拷贝构造函数
    cat2.show();
    return 0;
}

4.3 隐式调用构造函数

截止到目前,对于构造函数的调用都是显式调用

隐式调用构造函数的出现情况:

        (1)等号赋值时,等号左侧是对象类型,等号右边恰好是对象构造函数所需要的参数类型,这时就会把右侧值传入到构造函数中,相当于隐式调用构造函数

#include <iostream>
using namespace std;
class Test{
private:
    int number;
public:
    Test(int number)
        :number(number){}
    int get_number(){
        return number;
    }
};
int main(){
//    Test t1(100);  //显示调用构造函数
//    cout<<t1.get_number()<<endl;
//    Test*t2=new Test(8);  //显示调用构造函数
//    cout<<t2->get_number()<<endl;
//    delete t2;
//    t2=NULL;
//    Test t3(t1);  //显示调用构造函数
//    cout<<t3.get_number()<<endl;
    Test t4=9;  //隐式调用构造函数
    cout<<t4.get_number()<<endl;
    Test t5=t4;  //隐式调用构造函数
    cout<<t5.get_number()<<endl;
    return 0;
}

        (2)隐式调用构造函数,一般在程序员不自知的情况下产生的,需要规避掉,可以用explicit关键字屏蔽

class Test{
private:
    int number;
public:
    explicit Test(int number)
        :number(number){}
    int get_number(){
        return number;
    }
};

http://www.ppmy.cn/embedded/163419.html

相关文章

如何在 Visual Studio Code 中使用 DeepSeek R1 和 Cline?

让我们面对现实吧&#xff1a;像 GitHub Copilot 这样的 AI 编码助手非常棒&#xff0c;但它们的订阅费用可能会在你的钱包里烧一个洞。进入 DeepSeek R1 — 一个免费的开源语言模型&#xff0c;在推理和编码任务方面可与 GPT-4 和 Claude 3.5 相媲美。将它与 Cline 配对&#…

游戏数据中枢系统的架构设计与实现——以GameDataOrchestrator为核心的模块化数据管理体系

一、架构全景与设计哲学 本文将以重构后的GameDataOrchestrator为核心&#xff0c;深入剖析现代游戏引擎中的数据管理系统设计。该架构采用"分治-聚合"的双向管理模式&#xff0c;通过七大核心模块的有机协作&#xff0c;构建了层次分明、职责明确的数据管理体系。我…

细胞计数专题 | LUNA-FX7™新自动对焦算法提高极低细胞浓度下的细胞计数准确性

现代细胞计数仪采用自动化方法&#xff0c;在特定浓度范围内进行细胞计数。其上限受限于在高浓度条件下准确区分细胞边界的能力&#xff0c;而相机视野等因素则决定了下限。在图像中仅包含少量可识别细胞或特征的情况下&#xff0c;自动对焦可能会失效&#xff0c;从而影响细胞…

【简历优化】性能调优 — 编程性能调优篇

&#x1f60a;你好&#xff0c;我是小航&#xff0c;一个正在变秃、变强的文艺倾年。 &#x1f514;本文讲解【简历优化】性能调优 — 编程性能调优篇&#xff0c;期待与你一同探索、学习、进步&#xff0c;一起卷起来叭&#xff01; 目录 一、编程性能调优字符串String 发展优…

聊聊 IP 地址和端口号的区别

在计算机网络中&#xff0c;两个基本概念对于理解设备如何通过网络进行通信至关重要。IP 地址和端口号是 TCP/IP 的典型特征&#xff0c;其定义如下&#xff1a;IP 地址是分配给连接到网络的每台机器的唯一地址&#xff0c;用于定位机器并与其通信。相反&#xff0c;端口号用于…

【Windows使用VNC和Cpolar实现跨平台高安全性的远程桌面在线连接】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【C++】基础入门(详解)

&#x1f31f; Hello&#xff0c;我是egoist2023&#xff01; &#x1f30d; 种一棵树最好是十年前&#xff0c;其次是现在&#xff01; 目录 输入&输出 缺省参数(默认参数) 函数重载 引用 概念及定义 特性及使用 const引用 与指针的关系 内联inline和nullptr in…

DeepSeek 突然来袭,AI 大模型变革的危机与转机藏在哪?

随着人工智能技术的飞速发展&#xff0c;大模型领域不断涌现出具有创新性的成果。DeepSeek 的横空出世&#xff0c;为 AI 大模型领域带来了新的变革浪潮。本文将深入探讨 DeepSeek 出现后 AI 大模型面临的危机与转机。 冲冲冲&#xff01;&#xff01;&#xff01; 目录 一、…