zoukankan      html  css  js  c++  java
  • CPP_类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

    类默认函数:构造函数,拷贝构造函数,赋值函数和析构函数

    // person.h
    #ifndef _PERSON_H_
    #define _PERSON_H_
    
    class Person{
        public :
            Person();
            Person(int myage, char *myname);
            Person(const Person &a);
            Person& operator=(const Person& other);
            ~Person(void);
    
            void set_age(int myage);
            int get_age(void) const;
            void set_other_age(Person &a, int b); 
            void print() const;
    
        private:
            int age;
            char *name;
    };
    
    #endif
    // person.cc
    #include "person.h"
    
    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    
    using namespace std;
    
    Person::Person():age(10), name(NULL)
    {
        //nothing   
        cout<<"no param construct!"<<endl;
    }
    
    Person::Person(int myage, char *myname)
    {
        age = myage;
        if(myname != NULL){
            name = new char[strlen(myname) + 1];
            this->print();
            strcpy(name, myname);
        }
        cout<<"param construct!"<<endl;
    }
    
    Person::Person(const Person &a)
    {
        cout <<"copy constructor!"<<endl;
        if(a.name != NULL){
            name = new char[strlen(a.name)+1];
            this->print();
            strcpy(name, a.name);
            age = a.age;
        } else {
            name = NULL;
            age = 10;
        }
    }
    Person& Person::operator=(const Person &a)
    {
        cout <<"= constructor!"<<endl;
        if(&a == this){
            return *this;
        }
    
        if(name != NULL){
            delete [] name;
            name = NULL;
        }
        if(a.name != NULL){
            name = new char[strlen(a.name)+1];
            this->print();
            strcpy(name, a.name);
            age = a.age;
        } else {
            name = NULL;
            age = 10;
        }
    
        return *this;
    }
    
    
    Person::~Person()
    {
        if(NULL != name){
            delete [] name;
            name = NULL;
        }
        cout<<"destructor!"<<endl;
    }
    void Person::set_age(int myage)
    {
        age = myage;
    }
    
    int Person::get_age(void) const
    {
        return age;
    }
    
    void Person::set_other_age(Person& a, int b)
    {
        a.age = b;
        //a.set_age(b);
    }
    
    void Person::print() const
    {
        if(name != NULL)
            cout <<"value:" << name;
        cout<< " name=" << static_cast<void*> (name) << endl;
    }
    // main.cc
    #include "person.h"
    
    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
        Person a(11, "xiaohhhhh");  
        Person b(13, "mingttttt");
        Person m;
    
        m = b;
        a.print();
        b.print();
        m.print();
    
        Person n(13, "qing");
        b=n;
        a=n;
        m=n;
        a.print();
        b.print();
        m.print();
    
        return 0;
    }

    构造函数、析构函数和赋值函数是类最重要的函数,被称为The Big Three。
    与其他成员函数相比,The big three特殊之处在于,如果代码中没有提供这些函数的实现,C++编译器自动合成缺省的函数实现。
    有指针成员变量的类一定要提供The Big Three的实现,即使没有指针变量,作为良好的编程习惯也应该提供The Big Three的实现。

    1. 构造函数

    和类同名,无返回值,用来初始化类的对象。
    构造函数可重载。
    编译器提供默认无参构造函数,若声明新的,则采用新的构造函数。一般多应创建一个无参的构造函数,因为创建了有参构造函数后,默认的无参构造函数被覆盖。
    构造函数在对象创建后马上调用。
    Person a; //调用无参构造函数
    Person a(20, "Xiaoming"); //调用两参构造函数
    Person(int age=0, const char *name = NULL);构造函数,相当于创建无参或两参构造函数。

    2.拷贝构造函数

    Person(const Person &a);
    如果没有提供拷贝构造函数,编译器会默认提供一个(执行逐个成员初始化,将新对象初始化为原对象的副本,这里的逐个是指编译器将现有对象的每个非static成员,依次复制到正在创建的对象)。
    如果类有指针成员变量或类数据成员管理资源(如打开一个文件),默认构造函数并不会自动分配指针所指向的空间(默认构造函数仅提供浅拷贝),需要添加拷贝构造函数实现深拷贝。
    默认拷贝构造函数实现浅拷贝:指针成员变量指向同一存储区域,而不是重新分配区域再赋值(深拷贝)。
    如果想禁止一个类的拷贝构造,需要将拷贝构造函数声明为private。

    3. 析构函数

    析构函数不可重载。
    类名前加~的函数,无参数,无返回值。
    先调用析构函数->后销毁对象。
    默认的析构函数不会释放指针成员变量分配的内存区域,可能造成内存泄露。有指针成员变量时必须实现析构函数。

    4. 赋值函数

    Person& operator=(const Person& other);
    基本与拷贝构造等价。如果想禁止一个类的赋值函数,需要将拷贝构造函数声明为private。
    Person b=a; //拷贝构造函数
    Person b;
    b = a; //赋值函数 operator=

    5. 构造函数的初始化列表

    const变量必须用初始化列表进行初始化。
    Person():age(10), name(NULL)中":age(10),name(NULL)"为初始化列表。

    6. set_other_age()同一类的不同对象可以访问其他对象的私有数据。

    7. this指针

    每个成员方法都包含一个隐藏参数this,this是一个对象的指针,指向调用函数的对象。
    判断自赋值:

    if(this == &a){
    return *this;
    }
  • 相关阅读:
    Web.py Cookbook 简体中文版
    'IContextMenu' : no GUID has been associated with this object问题的解决
    switchflow/switchflow/asiohttp at master · baus/switchflow · GitHub
    面试体验:Facebook 篇
    Nodejs抓取非utf8字符编码的页面
    小体会
    做socket保持长连接的一些心得
    【资料整理】Socket编程之非阻塞connect(二)
    Less copies in Python with the buffer protocol and memoryviews
    » 文档与笔记利器 reStructuredText 和 Sphinx Wow! Ubuntu
  • 原文地址:https://www.cnblogs.com/embedded-linux/p/9613271.html
Copyright © 2011-2022 走看看