【用示例学习与理解C++系列】类的构造方法

2023-05-16

前言

本文主要是通过简单的示例,去学习与理解C++类的构造方法

构造方法的作用

为什么存在构造方法?为什么需要构造方法?
那是因为当我们在代码中定义一类变量(实例化一个类的实例/对象时)编译会帮我们申请对象所需要的内存(编译会给我们定义类生成默认的无参构造方法、析构方法、拷贝构造方法以及赋值构造方法)然后会根据类变量的使用情况(具体的代码语法与使用的上下文)调用对应的构造方法给对象分配内存和初始化类的成员变量,当我们有"扩展"的需求时就需要自定义有参型的构造方法和重写/覆盖无参构造方法、析构方法、拷贝方法方法等等。

构造方法的类型

构造方法的分类

  1. 默认构造方法/无参构造方法
  2. 普通有参构造方法(有两个以上参数的)(即除了转化构造、拷贝构造方法外的有参构造方法)
  3. 转换构造方法(有而只有一个参数)
  4. 拷贝构造方法(支持重载,即可以有多个)
  5. 赋值构造方法(严格来说不算构造方法,它是赋值运行符重载)

所有的构造方法的方法名是类名,且没有返回值(赋值构造方法除外)

接下具体看下各个构造方法的使用情况与相关的知识点

默认构造方法

  1. 默认构造方法是无参,无返回值
  2. 默认构造方法编译器会帮生成一下,如果我们没有定义的话
  3. 如果定义了其它的构造方法,编译器就不会帮忙生成默认的,这时候需要手动添加
class Person {
private:
    int age;
public:
//    Person() {
//        cout << "无参构造方法" << endl;
//    };
	//定义了拷贝构造方法
    Person(const Person& p) {
        cout << "拷贝构造方法, age = " << age << endl;
        this->age = p.age;
    }

    ~Person() {
        cout << "析构方法, age = " << age << endl;

    }

    int getAge() {
        return this->age;
    }

    void setAge(int age) {
        this->age = age;
    }

};

void printPerson(Person p) {
    cout << "Person, age = " << p.getAge() << endl;
}

Person retPerson() {
    Person a; 
    / **
    这里会报错,clion下,clang编译报错,
    No matching constructor for initialization of 'Person' candidate constructor not viable: requires single argument 'p', but no arguments were provided
    */
    a.setAge(20);
    return a;
}

普通有参构造方法

  1. 这里的有参是指有形参
  2. 方法命是类名,有两个以上的参数(一个的话就是类型转化构造方法了)
  3. 支持重载,即可以有很多个普通有参构造方法
#include <iostream>

using namespace std;

class Person {
private:
    int age;
    bool isVip;
    float height;
public:
    Person() {
        cout << "无参构造方法" << endl;
    };

    Person(int age, bool isVip) {
        cout << "有参构造方法1" << endl;
        this->age = age;
        this->isVip = isVip;
    }

    Person(int age, float height) {
        cout << "有参构造方法2" << endl;
        this->age = age;
        this->height = height;
    }

    Person(const Person &p) {
        cout << "拷贝构造方法, age = " << age << endl;
        this->age = p.age;
    }

    ~Person() {
        cout << "析构方法, age = " << age << endl;
    }

    int getAge() {
        return this->age;
    }

    void setAge(int age) {
        this->age = age;
    }

};


void printPerson(Person p) {
    cout << "Person, age = " << p.getAge() << endl;
}

Person retPerson() {
    Person a;
    a.setAge(20);
    return a;
}

int main() {


    {
        Person a(10, 170.0f);
        Person b(18, true);
    }

    return 0;
}

类型转化构造方法

  • 有且只有一个参数(参数类型不能是本身类)
  • 在发生隐式类型转换时被调用
#include <iostream>

using namespace std;

class Person {
private:
    int age;
    bool isVip;
    float height;
public:
    Person() {
        cout << "无参构造方法" << endl;
    };

    Person(int age) {
        cout << "转换构造方法1" << endl;
        this->age = age;
    }

    ~Person() {
        cout << "析构方法, age = " << age << endl;
    }

};

void printPerson(Person p) {
    cout << "Person, age = " << p.getAge() << endl;
}

int main() {
    {
       //printPerson的形参数是Persion类型,但由于定义了Person(int age),固能支持12到Persion的隐式类型转化
       printPerson(12);
    }
    return 0;
}

代码运行结果如下
在这里插入图片描述

拷贝构造方法

  1. 默认编译器会帮生成一个
  2. 被拷贝的对象的形参引用必须带const修饰,即是一个常量引用
  3. 除拷贝的对象的形参外,还可以有其它的形,但需要有默认值
  4. 复制本类的一个实例
  5. 函数形参为一个对象,还有方法的形参类的值传递时,还有方法返回值是对象(这种情况现代编译器已经优化过不会再调用次拷贝构造方法了)时会调用到该方法
#include <iostream>

using namespace std;

class Person {
private:
    int age;
    bool isVip;
    float height;
public:
    Person() {
        cout << "无参构造方法" << endl;
    };

    Person(const Person &p) {
        cout << "拷贝构造方法, age = " << age << endl;
        this->age = p.age;
    }

//    ~Person() {
//        cout << "析构方法, age = " << age << endl;
//    }

    int getAge() {
        return this->age;
    }

    void setAge(int age) {
        this->age = age;
    }

};


void printPerson(Person p) {
    cout << "pint Person, age = " << p.getAge() << endl;
}

Person retPerson() {
    Person a;
    a.setAge(20);
    return a;
}

int main() {


    {
        cout << ">> case1, 方法返回对象" << endl;
        Person a = retPerson();
    }

    {
        cout << ">> case2,形参对象" << endl;
        Person a;
        a.setAge(18);
        printPerson(a);
    }

    {
        cout << ">>case3, 显示调用拷贝构造" << endl;
        Person a;
        a.setAge(20);
        Person b(a);
    }
    return 0;
}

代码运行结果如下
在这里插入图片描述

赋值构造方法

  1. 默认编译器会帮生成一个
  2. 被拷贝的对象的形参引用必须带const修饰,即形参是一个常量引用
  3. 是对=号操作符的重载,有返回值且是类的引用类型,所以是赋值操作的时候被调用
#include <iostream>

using namespace std;

class Person {
private:
    int age;
    bool isVip;
    float height;
public:
    Person() {
        cout << "无参构造方法" << endl;
    };

    Person(const Person &p) {
        cout << "拷贝构造方法, age = " << age << endl;
        this->age = p.age;
    }

    Person& operator=(const Person &p) {
        this->age = p.age;
        cout << "赋值构造方法, age = " << age << endl;
        return *this;
    }

    int getAge() {
        return this->age;
    }

    void setAge(int age) {
        this->age = age;
    }

};

Person retPerson() {
    Person a;
    a.setAge(20);
    return a;
}

int main() {

    {
        Person a;
        a.setAge(20);
        Person b;
        b = a; //这里是真正的赋值操作, Person b = a; 这种写法是定义类变量,调用是拷贝构造方法
    }
    return 0;
}

代码运行结果如下
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【用示例学习与理解C++系列】类的构造方法 的相关文章

  • 千万不要去外国当程序员

    今天我来讲讲我这样的一个普通程序员是如何从有想法 xff0c 到实施 xff0c 到最后来到欧洲务工的 整个过程很曲折 xff0c 文章有点长 xff0c 大家给点耐心 如果看不下去请直接翻到最后 xff0c 有总结 个人背景 为了避免有人
  • 逻辑思维能力选择题30道

    逻辑思维能力选择题30道 这些题目都是作者选取于网络 xff0c 靠自己动脑做出来的是最棒的 1 有一个有钱人想让你和他玩一个游戏 xff0c 你在纸上写下一句话 xff0c 并作出选择 选择1 xff1a 如果你写的是实话 xff0c 那
  • 单位换算表大全

    长度 1千米 km 61 0 621英里 mile 1米 m 61 3 281英尺 ft 61 1 094码 yd 1丝米 dmm 61 1忽米 cmm 61 1丝 61 0 01毫米 61 0 001厘米 1厘米 cm 61 0 394英
  • Debian配置CA_配置Apache2使用ssl_配置http连接自动跳转到https

    需要使用到两台Debian服务器 xff0c 一台作为ca端 xff0c 一台作为Apache端 ca端IP xff1a 192 168 200 129 Apache端IP xff1a 192 168 200 131 以下是CA端配置 xf
  • 重量(计量单位)英文缩写和转换表

    重量的缩写是W 一 质量单位换算 xff1a 1长吨 xff08 long ton xff09 61 1 016吨 xff08 t xff09 1千克 xff08 kg xff09 61 2 205磅 xff08 lb xff09 1磅 x
  • 逻辑学三大定律是什么?

    逻辑思维三大定律 同一律 xff0c 矛盾律 xff0c 排中律 同一律 xff1a A 是 A 前后思维中 xff0c 概念要同一 白马非马论违反同一律 商家的买一赠一 xff0c 前后两个一不是同一个概念 违反同一律 矛盾律 xff1a
  • 逻辑学三大定律

    1 同一律就是前后提及概念 论题要是同一个 xff0c 不是同一个就是不合逻辑的 看这句话 xff0c 人有几百万年的历史 xff0c 你没有几百万年的历史 xff0c 所以你不是人 xff0c 典型的三段论 xff0c 大前提 xff0c
  • LeetCode:移除元素

    给你一个数组 nums 和一个值 val xff0c 你需要 原地 移除所有数值等于 val 的元素 xff0c 并返回移除后数组的新长度 不要使用额外的数组空间 xff0c 你必须仅使用 O 1 额外空间并 原地 修改输入数组 元素的顺序
  • C#高级特性(反射)

    今天来讲解反射的应用 xff1a 一 反射是什么 xff1f 简诉一下 xff0c 反射就是 Net Framework 的一个帮助类库 xff0c 可以获取并使用metadata xff08 元数据清单 xff09 xff1b 说的通俗易
  • Linux 操作命令 c

    1 打开终端的快捷键 ctr 43 alt 43 t 2 终端字体放大 ctr 43 shift 43 43 3 终端字体缩小 ctr 43 4 ls 查看当前目录的下文件信息 5 pwd 当前当前目录的路径 6 touch 创建一个文件
  • java实现平面4点最小距离

    已知平面上若干个点的坐标 需要求出在所有的组合中 xff0c 4个点间平均距离的最小值 xff08 四舍五入 xff0c 保留2位小数 xff09 比如有4个点 xff1a a b c d 则平均距离是指 xff1a ab ac ad bc
  • 【HTTPS】TLS/SSL握手失败的场景分析

    0 背景知识 TLS SSL握手的过程参考 SSL握手过程图解 1 常见报错 1 1 SSLHandshakeException handshake failure 1 1 1 TLS SSL协议版本不匹配 自从TLS 1 2版本在2008
  • 使用RKE部署Rancher v2.5.8 HA高可用集群

    文章目录 一 了解 Rancher1 关于Helm2 关于RKE3 关于K3S4 Rancher 名词解释4 1 仪表盘4 2 项目4 3 多集群应用4 4 应用商店4 5 Rancher Server URL4 6 RKE 模板4 7 G
  • SQL练习题

    网上有一篇关于SQL的经典文章 xff0c 超经典SQL练习题 xff0c 做完这些你的SQL就过关了 xff0c 引用和分析它的人很多 xff0c 于是今天复习SQL的时候找来练了练手 原作者用的是SQL Server 2008 xff0
  • VS2015编译报MS8020错误

    新装的VS2015 xff0c 调试旧的代码报错 xff0c 信息如下 xff1a MSB8020 The build tools for v120 Platform Toolset 61 39 v120 39 cannot be foun
  • 1001. Poker (思维 / 模拟)(2020年百度之星*程序设计大赛-初赛二)

    传送门 思路 xff1a 嗐 xff0c 又是这种模拟题 xff0c 每次都不长记性看数据范围 xff0c 非得傻傻的去循环模拟T一次才知道思考 呜呜呜太菜了 既然每次至少拿出m xff0c 且求的是最多次数 xff0c 那我们每次就拿m出
  • ffmpeg/libavformat/tcp.c中getaddrinfo在IOS下的问题

    IOS的播放器用了ffmpeg 3 1 发现不支持ipv6 跟踪到ffmpeg libavformat tcp c下的getaddrinfo函数 xff0c 发现执行完之后 xff0c 如果是由ipv4合成ipv6的时候 会把端口设成0 所
  • iOS UIImagePickerController 自定义导航条背景、标题和按钮的颜色

    UIImagePickerController span class token operator span imagePickerController span class token operator 61 span span clas
  • centos7.9安装mysql8.0-参考官网简易安装文档,简洁且必成功

    目录 文章目录 目录一 前面的话二 环境三 选择什么下载安装方式四 安装过程1 到官网选择合适的yum repositoty版本2 把这个rpm包下载下来3 使用yum工具添加这个mysql的yum repo4 安装mysql5 启动服务器
  • Mysql8.0设置允许远程连接

    Mysql8 0设置允许远程连接 1 登录mysql 2 选择mysql数据库 3 修改user表使其root用户可以通过远程连接 4 刷新权限 1 登录mysql mysql uroot p 1 2 选择mysql数据库 user mys

随机推荐