C++学习笔记_001_对象特性

万事开头难,形成习惯是最重要的。

学习基于B站黑马的视频,从类和对象部分开始,笔记有错误的地方欢迎指正。

 1.构造函数和析构函数

构造函数(constructor)和析构函数(destructor)分别负责对象(class)的初始化和清理工作,定义类时,不在类的内部提供的话编译器(compiler)会自动提供空实现。

构造函数名和类名相同,无返回值且不用写void,可重载,创建class时自动调用且只调用一次。

析构函数名和类名相同,函数名前加符号~,无返回值且不用写void,无参数(不可重载),class销毁前调用且只调用一次。

构造函数分类:1.按参数分 -- 有参&无参(默认) 2.按类型分 -- 普通&拷贝

三种转换方式:1.括号法 2.显示法 3.隐式转换法

#include <iostream>
using namespace std;

class person{
public:
    //构造函数
    person(){
        cout << "构造函数的调用" << endl;
    }
    person(int a){
        age = a;
        cout << "有参构造函数的调用" << endl;
    }
    person(const person &p){
        age = p.age
        cout << "拷贝构造函数的调用" << endl;
    }

    //析构函数
    ~person(){
        cout << "析构函数的调用" << endl;
    }

    int age; 
};

void test(){
    //1.括号法
    person p1; //默认构造,栈上的数据,test执行完毕后会将对象释放,会出现析构调用字样
    person p2(10); //有参构造
    person p3(p2); //拷贝构造
    //注意:调用默认构造时不要加(),会被编译器认为是在函数声明而不是创建对象
    //如:person p1();

    //2.显示法
    person p1; //默认
    person p2 = person (10); //有参
    person p3 = person (p2); //拷贝
    
    //3. 隐式转换法
    person p1; //默认
    person p2 = 10; //有参
    person p3 = p2; //拷贝
    
    cout << "p2的年龄为:" << p2.age << endl;
}

int main(){
    //test();
    person p; //对象创建后系统中断,不会出现析构调用字样
    system("pause");
    return 0; 
}

构造函数的调用规则

1.用户定义有参构造,C++不再提供默认无参构造,但提供默认拷贝构造。

2.用户定义拷贝构造,C++不再提供其他构造。

2.深拷贝和浅拷贝

浅拷贝(shallow copy):简单的赋值拷贝操作

深拷贝(deep copy):在堆区(heap)重新申请空间进行拷贝操作

#include <iostream>
using namespace std;

class person {
public:
    //构造函数
    person() {
        cout << "默认构造函数的调用" << endl;
    }
    person(int age, int height) {
        m_age = age;
        m_height = new int(height);
        cout << "有参构造函数的调用" << endl;
    }


    //析构函数
    ~person() {
        //将堆区开辟数据释放
        if (m_height != NULL) {
            delete m_height;
            m_height = NULL;
        }
        cout << "析构函数的调用" << endl;
    }   
    
    int m_age; //年龄
    int *m_height; //身高
};

void test01() {
    person p1(18, 160);

    cout << "p1年龄为:" << p1.m_age << "身高为:" << *p1.m_height << endl;

    person p2(p1);

    cout << "p2的年龄为:" << p2.m_age << "身高为:" << *p2.m_height << endl;
}

int main() {
    test01();

    system("pause");
    return 0;
}

上面的代码为利用编译器提供的拷贝构造函数进行拷贝操作,此时为浅拷贝,会导致堆区内存的重复释放,导致系统报错:

利用深拷贝解决问题:

//在类中自定义拷贝构造如下
person(const person &p) {
    cout << "拷贝构造函数的调用" << endl;
    m_age = p.m_age;
    m_height = new int(*p.m_height); // 深拷贝操作,开一个新空间
    // 编译器的默认实现为:m_height = p.m_height; 
}

如果有属性在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝问题。

3.类对象作为类成员

当其他类对象作为本类成员,构造时先构造该类对象,再构造自身,析构的顺序反之。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值