美文网首页
c++面向对象-构造、析构、初始化列表

c++面向对象-构造、析构、初始化列表

作者: cabin523 | 来源:发表于2019-10-23 17:35 被阅读0次

    构造函数

    构造函数是指创建对象的时候,会调用的函数。
    C++构造函数可以重载,指针或者对象均可调用构造函数。

    class Person
    {
    public:
        int m_age;
    
        Person() {
            this->m_age = 10;
        }
    
        Person(int age) {
            this->m_age = age;
        }
    };
    
    Person* p0 = new Person(20);
    Person p1;
    cout << p0->m_age << endl; //输出20
    cout << p1.m_age << endl;  //输出10
    

    析构函数

    析构函数是指对象即将销毁的时候,会调用的函数,析构函数无参,不可重载,只有一个。

    class Person {
    public:
        ~Person() {}
    };
    

    构造与析构的顺序

    构造从父类到子类进行构造,
    析构从子类到父类进行析构。
    如下打印顺序为:
    Person() -> Student() -> ~Student() -> ~Person()

    class Person
    {
    public:
        Person() { cout << "Person()" << endl; }
        ~Person() { cout << "~Person()" << endl; }
    };
    
    class Student: Person
    {
    public:
        Student() { cout << "Student()" << endl; }
        ~Student() { cout << "~Student()" << endl; }
    };
    

    初始化列表

    初始化列表是一种便捷初始化成员变量的方式,而且只能在构造函数中使用,初始化的顺序只和声明顺序有关。

    class Person
    {
        int m_age;
        int m_heighht;
    
        Person(int m_age, int m_height) {
            this->m_age = m_age;
            this->m_heighht = m_heighht;
        }
    };
    
    //初始化列表
    class Person
    {
        int m_age;
        int m_heighht;
    
        Person(int age, int height): m_age(age), m_heighht(height) {}
    };
    

    初始化列表-构造函数调用构造函数

    //调用自身构造
    class Person
    {
    public:
        int m_age;
        int m_height;
    
        Person(int age, int height): m_age(age), m_height(height) {}
    
        Person() :  Person(18, 180) {}
    };
    
    //调用父类构造
    class Student: Person
    {
        int m_no;
    
        Student(int age, int height, int no) : Person(age, height), m_no(no) {}
    };
    

    拷贝构造函数

    1. 拷贝构造函数是构造函数中的一种。
    2. 拷贝构造函数是指在用已存在的对象创建新对象的时候,调用的构造函数方法。比如在new 类(对象),或者=赋值时会调用。
    3. 拷贝构造函数写法都是固定的,const XX &x。
    class Car
    {
    public:
        int m_price;
    
        Car(int price) : m_price(price) {}
        Car(const Car& car) {
            this->m_price = car.m_price;
        }
    };
    
    Car a(100);
    Car b = a;
    Car c(a);
    

    深拷贝和浅拷贝

    浅拷贝(编译器默认为浅拷贝)

    1. 浅拷贝是将一个对象成员变量的所有值拷贝到另一个对象
    2. 即便成员变量是指针,也会原封不动的拷贝过去,这样就有可能导致内存多次释放的问题。

    深拷贝(用户手动控制的)

    深拷贝是对象中指针类的成员变量,在构造函数或者拷贝构造函数中,单独申请内存来存放数据,该内存的生命周期由对象来控制,如以下例子即是深拷贝用法:

    class Car
    {
        void copyName(const char* name) {
            if (name == nullptr) return;
    
            this->m_name = new char[strlen(name) + 1]{};
            strcpy(this->m_name, name);
        }
    public:
        int m_price;
        char* m_name;
    
        Car(int price, const char* name) : m_price(price) {
            copyName(name);
        }
    
        Car(const Car& car) {
            this->m_price = car.m_price;
            copyName(car.m_name);
        }
    
        ~Car() {
            if (this->m_name != nullptr) {
                delete[] this->m_name;
                this->m_name = nullptr;
            }
        }
    };
    
    Car* c1 = new Car(10000, "Toyota");
    Car* c2 = new Car(15000, "BMW");
    Car c3 = *c2;
    Car* c4 = new Car(*c1);
    delete c1, c2, c4;
    

    隐式调用拷贝构造函数

    1. 函数参数中使用对象型参数,会调用隐式拷贝,增加内存开销,尽量采用引用&来传递,而不要直接使用对象,如下所示,则在传参过程中,调用了拷贝构造。
    class Car
    {
    public:
        int m_price;
        Car() : m_price(0) {}
        Car(int price) : m_price(price) {}
        Car(const Car& car) : m_price(car.m_price) {}
    };
    
    //调用该函数的时候,会触发传参  Car car = 传入的car
    //因此会调用拷贝构造函数,造成额外的开销
    void test1(Car car) {
    
    }
    
    1. 作为函数的返回值的时候。
    Car test2() {
        Car car(20);
        return car;
    }
    //会调用两次构造函数,
    //第一次是Car(int price)
    //第二次是Car(const Car& car) : m_price(car.m_price)
    Car car2 = test2();
    

    相关文章

      网友评论

          本文标题:c++面向对象-构造、析构、初始化列表

          本文链接:https://www.haomeiwen.com/subject/pnukvctx.html