zoukankan      html  css  js  c++  java
  • C++ 拷贝构造函数

    拷贝构造函数:以拷贝的方式初始化一个对象时,会调用拷贝构造函数。

    拷贝构造函数只有一个参数,它的类型是当前类的const引用,且任何额外参数都有默认值。

    #include <iostream>
    #include <string>
    using namespace std;
    
    class Student{
    public:
        Student(string name = "", int age = 0, float score = 0.0f);  //普通构造函数
        Student(const Student &stu);  //拷贝构造函数(声明)
    public:
        void display();
    private:
        string m_name;
        int m_age;
        float m_score;
    };
    Student::Student(string name, int age, float score): m_name(name), m_age(age), m_score(score){ }
    //拷贝构造函数(定义)
    Student::Student(const Student &stu){
        this->m_name = stu.m_name;
        this->m_age = stu.m_age;
        this->m_score = stu.m_score;
       
        cout<<"Copy constructor was called."<<endl;
    }
    void Student::display(){
        cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
    }
    
    int main(){
        Student stu1("小白", 16, 90.5);
        Student stu2 = stu1;  //调用拷贝构造函数
        Student stu3(stu1);  //调用拷贝构造函数
        stu1.display();
        stu2.display();
        stu3.display();  
        return 0;
    }
    

    为什么必须是当前类的引用呢?

    如果拷贝构造函数的参数是当前类的对象,那么在调用拷贝构造函数时,会将另外一个对象直接传递给形参,这本身就是一次拷贝,会再次调用拷贝构造函数,陷入死循环。

    为什么是const引用?

    原因1:拷贝构造函数的目的是用其他对象的数据来初始化当前对象,并没有期望更改其他对象的数据,使用const限制后,这个含义更加明确了。

    原因2:因为const类型不能转换为非const类型,如果不是const引用做形参,就不能将const对象传递给形参。即不能使用const对象来初始化当前对象了。

    默认拷贝构造函数

    如果程序员没有显式的定义拷贝构造函数,那么编译器就会自动生成一个默认拷贝构造函数。

    什么时候必须显式定义拷贝构造函数?

    当前类持有其他资源时,如动态分配的内存、打开的文件、指向其他数据的指针、网络连接等,默认拷贝构造函数不能拷贝这些资源,此时必须显式的定义拷贝构造函数。

    什么时候调用拷贝构造函数?

    以拷贝的方式初始化对象时调用拷贝构造函数。

    初始化对象:为对象分配内存后第一次向内存中填充数据,这个过程会调用构造函数。只要创建对象,就会调用构造函数。

    初始化:在定义的同时进行赋值
    赋值:定义完成以后再赋值

    #include <iostream>
    #include <string>
    using namespace std;
    class Student{
    public:
        Student(string name = "", int age = 0, float score = 0.0f);  //普通构造函数
        Student(const Student &stu);  //拷贝构造函数
    public:
        Student & operator=(const Student &stu);  //重载=运算符
        void display();
    private:
        string m_name;
        int m_age;
        float m_score;
    };
    Student::Student(string name, int age, float score): m_name(name), m_age(age), m_score(score){ }
    //拷贝构造函数
    Student::Student(const Student &stu){
        this->m_name = stu.m_name;
        this->m_age = stu.m_age;
        this->m_score = stu.m_score;
        cout<<"Copy constructor was called."<<endl;
    }
    //重载=运算符
    Student & Student::operator=(const Student &stu){
        this->m_name = stu.m_name;
        this->m_age = stu.m_age;
        this->m_score = stu.m_score;
        cout<<"operator=() was called."<<endl;
       
        return *this;
    }
    void Student::display(){
        cout<<m_name<<"的年龄是"<<m_age<<",成绩是"<<m_score<<endl;
    }
    int main(){
        //stu1、stu2、stu3都会调用普通构造函数Student(string name, int age, float score)
        Student stu1("小明", 16, 90.5);
        Student stu2("王城", 17, 89.0);
        Student stu3("陈晗", 18, 98.0);
       
        Student stu4 = stu1;  //调用拷贝构造函数Student(const Student &stu)
        stu4 = stu2;  //调用operator=()
        stu4 = stu3;  //调用operator=()
       
        Student stu5;  //调用普通构造函数Student()
        stu5 = stu1;  //调用operator=()
        stu5 = stu2;  //调用operator=()
       
        return 0;
    }
    
    /*运行结果:*/
    Copy constructor was called.
    operator=() was called.
    operator=() was called.
    operator=() was called.
    operator=() was called.
    
  • 相关阅读:
    调停者模式
    组合模式
    单例模式
    策略模式
    代理模式
    AJPFX简述Context.startService()和Context.bindService
    AJPFX简述abstract class和interface的区别
    AJPFX关于抽象类和接口的区别
    AJPFX关于StringBuffer,StringBuilder类 总结(一)
    AJPFX关于StringBuffer,StringBuilder类总结(二)
  • 原文地址:https://www.cnblogs.com/xiaobaizzz/p/12353713.html
Copyright © 2011-2022 走看看