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

前言

本文主要是通过简单的示例,去学习与理解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;
}

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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值