美文网首页
C++面向对象(2)

C++面向对象(2)

作者: yeshan333 | 来源:发表于2018-10-10 22:55 被阅读7次

    类的构造函数(Constructor)和析构函数(Destructor)

    <iframe src="http://open.iqiyi.com/developer/player_js/coopPlayerIndex.html?vid=c5d7868e19457dd682738eee9b4b05af&tvId=11980807509&accessToken=2.f22860a2479ad60d8da7697274de9346&appKey=3955c3425820435e86d0f4cdfe56f5e7&appId=1368&height=50%&width=100%" frameborder="0" allowfullscreen="true" width="100%" height="100%"></iframe>

    • 构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。构造函数的名称与类的名称是完全相同的,并且不会反回任何类型,也不会反回void。
    • 析构函数也是类的一种特殊的成员函数,它会在每次删除所创建的对象时执行。函数名称与类的名称完全相同,只是在前面加了个~波浪线作为前缀,它不会返回任何值,也不能带有任何参数。

    1.构造函数(Constructor)

      当我们定义一个类的对象时,系统就会自动调用它,进行专门的初始化对象用。如果我们没有定义构造函数,系统会默认生成一个默认形式,隐藏着的构造函数,这个构造函数的函数体是空的,它不具有任何功能。

    #include<iostream>
    #include<Cstring>
    using namespace std;
    
    class Student
    {
        private:
        int num;
        char name[100];
        int score;
        public:
        Student(int n,char *str,int s);
        int print();
        int Set(int n,char *str,int s); 
    };
    
    Student::Student(int n,char *str,int s)//定义了一个带默认参数的构造函数 
    {
        num=n;
        strcpy(name,str);
        score=s;
        cout<<"Constructor"<<endl; 
    }
    
    int Student::print()
    {
        cout<<num<<" "<<name<<" "<<score;
        return 0;
    }
    
    int Student::Set(int n,char *str,int s)
    {
        num=n;
        strcpy(name,str);
        score=s;
    }
    
    int main()
    {
        Student A(1700710135,"yeshan",99);
        A.print();
        
        //Student C;这样定义对象会报错,因为我们在类中定义了一个带默认参数的构造函数 
        cout<<endl;
         
        Student B(1700710134,"xu jie",100);
        B.print();
        return 0;
    }
    
    image

    <font color="green">由于在程序中定义了一个带默认参数的构造函数,则系统不会再自动生成,这个时候定义对象时也要传入三个默认初始值,因为构造函数可以重载,可以有多个兄弟,系统会找最匹配的一个函数</font>

    2.析构函数(Destructor)

     对象销毁时自动调用的一个函数,析构函数不能重载,一个类只能有一个析构函数,析构函数有助于跳出程序前释放内存。

    #include<iostream>
    #include<Cstring>
    using namespace std;
    class Student
    {
        private:
        int num;
        char name[100];
        int score;
        public:
        Student(int n,char *str,int s);
        ~Student();
        int print();
        int Set(int n,char *str,int s); 
    };
    
    Student::Student(int n,char *str,int s)//构造函数 
    {
        num=n;
        strcpy(name,str);
        score=s;
        cout<<num<<" "<<name<<" "<<score<<" ";
        cout<<"Constructor"<<endl;
    } 
    
    Student::~Student()//析构函数 
    {
        cout<<num<<" "<<name<<" "<<score<<" ";
        cout<<"destructor"<<endl;
    }
    
    int Student::print()
    {
        cout<<num<<" "<<name<<" "<<score<<endl;
        return 0;
    }
    
    int Student::Set(int n,char *str,int s)
    {
        num=n;
        strcpy(name,str);
        score=s;
    }
    int main()
    {
        Student A(100,"dot",11);
        Student B(101,"cpp",12);
        return 0;
    }
    
    image

    <font color="green">对象A和B的构造函数的调用顺序以及构造函数的调用顺序,完全相反!原因在于A和B对象同属局部对象,也在栈区存储,也遵循“先进后出”的顺序!</font>

    拷贝构造函数

    拷贝构造函数是一种特殊的构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。
    它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。
    当定义一个新对象并用同一个类型的对象对它进行初始化时,将显示使用拷贝构造函。
    只包含类类型成员或内置类型(但不是指针类型)成员的类,无须显式地定义拷贝构造函数也可以拷贝。

    显示定义拷贝构造函数的情况:
    类有数据成员是指针;
    有成员表示在构造函数中分配的其他资源
    
    #include<iostream>
    using namespace std;
    
    class Age
    {
        public:
            int GetAge(void);
            Age(int age);           //Constructor
            Age(const Age& A);      //Copy Constructor
            ~Age();                 //Desconstructor
        private:
            int *ptr;
    };
    
    Age::Age(int age)
    {
        cout<<"调用构造函数"<<endl;
        ptr = new int;//为指针分配内存
        *ptr = age; 
    }
    
    Age::Age(const Age& A)
    {
        cout<<"调用拷贝构造函数,并为指针ptr分配内存"<<endl;
        ptr = new int;
        
        *ptr = *A.ptr;   //拷贝值 
    }
    
    Age::~Age()
    {
        cout<<"释放内存"<<endl;
        delete ptr;
    } 
    
    int Age::GetAge(void)
    {
        return *ptr; 
    }
    
    void print_age(Age A)
    {
        cout<<"the age: "<<A.GetAge()<<endl; //这里也调用了拷贝构造函数
    }
    int main()
    {
        Age member_1(10);
        
        Age member_2(member_2);//相当于Age member_2 = member_1;
        
        return 0;   
    } 
    
    image image
    image image image

    <font color="red">成员变量中加一个了指针成员,初始化中需要动态开辟内存,如果不自定义拷贝构造函数,而是用默认生成的,则会出现极大的安全隐患。
    默认的拷贝构造函数仅仅是进行数值赋值,并不能为指针开辟内存空间。相当于代码This->str=str.本质上也就是两个指针指向了一块堆空间。程序结束回收对象的时候,会调用自己的析构函数,释放这块内存空间,由于两个对象要调用两次,即delete两次,就会出现错误</font>
    <p align="right"><font size=4>引自</font></p>

    C++中的this指针

    对象中隐藏的指针

    • 每一个对象都能通过this指针来访问自己的地址。this指针是所有成员函数额隐含参数。因此在成员函数内部,它可以用来指向调用的对象。
    • 如果程序中有多个属于同一类的对象,因成员函数的代码仅有一份,所以为了区分它们是哪个对象调用的成员函数,编译器也是转化成this->成员函数这种形式来使用的。
    • 友元函数没有this指针,因为友元不是类的成员。只有成员函数才有this指针。
    #include<iostream>
    using namespace std;
    
    class Age
    {
        public:
            Age(int your_age=18)  //Constructor function 
            {
                cout<<"Constructor now"<<endl; 
                age=your_age;
            }
            int GetAge()
            {
                return age;
            }
            int compare(Age member)
            {
                return this->GetAge()>member.GetAge();   //看这里 
            }
        private:
            int age;
    };
    
    int main()
    {
        Age member_1(20),member_2(24);
        
        if(member_1.compare(member_2))
        {
            cout<<"member_1 is older than member_2"<<endl;
        }
        else
        {
            cout<<"member_1 is younger than member_2"<<endl;
        }
    }
    
    image

    关键字new和delete

    1. new(新建)用于新建一个对象。new 运算符总是返回一个指针。由 new 创建。
    2. delete(删除)释放程序动态申请的内存空间。delete 后面通常是一个指针或者数组 [],并且只能 delete 通过 new 关键字申请的指针。

    相关文章

      网友评论

          本文标题:C++面向对象(2)

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