1.构造函数

构造函数的特征

+ 名字和类名相同
+ 没有返回值
+ 不写构造函数会存在一个默认的构造函数(无参),如果写了,默认的就不存在
+ 构造函数不需要自己调用,创建对象的时候调用构造函数
+ 构造函数的长相决定了对象模样(参数个数)
+ 构造函数的作用: 一般来说就是为数据做初始化
+ 可以被重载(参数可以不同) ,这样的话可以满足构造不同的对象

namespace myData {
    class MM {
    public:
        MM() { cout << "调用默认构造函数" << endl; }
        MM(string name) 
        {
            this->name = name;
            age = 18;
        }
        MM(string name, int age) {
            this->name = name;
            this->age = age;
        }
        void print()
        {
            cout << name << "\t" << age << endl;
        }
    protected:
        string name;
        int age;
    };
}

int main()
{
    myData::MM* mm = new myData::MM("小可爱");
    myData::MM mm1 = { "小李子" };//也是调用构造函数
    return 0;
}

2.析构函数

+ 函数名是~加上类名
+ 没有返回值
+ 没有参数,所以析构函数只有一个
+ 对象死亡的时候会**自动调用**析构函数
+ 一般都有一个默认的析构,你写了就默认的就不存在
+ 类中数据成员做了动态内存申请,就需要手动写析构

namespace myData {
    class MM {
    public:
        MM() { cout << "调用默认构造函数" << endl; }
        MM(string name) 
        {
            this->name = name;
            age = 18;
            cout << "调用一个参数构造函数" << endl;
        }
        MM(string name, int age) {
            this->name = name;
            this->age = age;
            cout << "调用两个参数构造函数" << endl;
        }
        void print()
        {
            cout << name << "\t" << age << endl;
        }
        ~MM() { cout << "调用了析构函数" << endl; }
    protected:
        string name;
        int age;
    };
}

int main()
{
    myData::MM* mm = new myData::MM("张三",19);//此处先构造无名对象,然后赋值给mm指针,调用了两个参数的构造函数
    myData::MM mm1 = { "小李子" };//也是调用构造函数
    myData::MM mm2 = myData::MM();
    delete mm;

    /*
        结果:
                调用两个参数构造函数    (无名对象new一段内存,该段内存不会由析构函数自动释放,应主动释放,delete时调用析构函数)
                调用一个参数构造函数
                调用默认构造函数    (无名对象构建)
                调用了析构函数
                调用了析构函数
                调用了析构函数
    */

    return 0;//return后自动析构
}

3.构造顺序与析构顺序

namespace myData {
    class MM {
    public:
        MM() { cout << "调用默认构造函数" << endl; }
        MM(string name) 
        {
            this->name = name;
            age = 18;
            cout << "调用一个参数构造函数" << endl;
        }
        MM(string name, int age) {
            this->name = name;
            this->age = age;
            cout << "调用两个参数构造函数" << endl;
        }
        void print()
        {
            cout << name << "\t" << age << endl;
        }
        ~MM() { cout << name << endl; }
    protected:
        string name="@";
        int age;
    };
}
void print1(myData::MM obj)
{
}
void print2(const myData::MM& obj)
{
}
void print3(myData::MM* obj)
{

}
int main()
{
    //匿名对象:
    //正常对象:构造顺序与析构顺序相反
    {
        myData::MM a("A");
        myData::MM b("B");
        myData::MM c[3]{ {"C",1},{"D",2},{}};
    }//在作用域外释放
    /*
        结果:    调用一个参数构造函数
                调用一个参数构造函数
                调用两个参数构造函数
                调用两个参数构造函数
                调用默认构造函数
                @    //@表示无名对象
                D
                C
                B
                A
    */
    //new一个对象,delete时直接调用析构函数
    {
        myData::MM* a = new myData::MM("A");
        myData::MM b("B",19);
        delete a;
        a = nullptr;
    }
    /*
        结果:    调用一个参数构造函数
                调用两个参数构造函数
                A
                B
    */
    {
        myData::MM a("A");
        myData::MM("B");
        myData::MM c("C");
    }
    /*
        结果:    调用一个参数构造函数
                调用一个参数构造函数    
                B                        //没有管理的匿名对象直接消亡
                调用一个参数构造函数
                C
                A
    */
    //匿名对象转交所有权
    {
        myData::MM a("A");
        myData::MM b = myData::MM("B");//转正后归对象b管理
        myData::MM c("C");
    }
    /*
        结果:    调用一个参数构造函数
                调用一个参数构造函数
                调用一个参数构造函数
                C
                B
                A
    */
    //匿名对象当作函数参数,不论是赋值还是引用都直接消亡
    {
        print1(myData::MM("A", 20));
        print2(myData::MM("B"));
        print3(new myData::MM());
    }
    /*
        结果:    调用两个参数构造函数
                A
                调用一个参数构造函数
                B
                调用默认构造函数
    */
    //静态对象最后被释放
    {
        myData::MM a("A");
        static myData::MM b("B",22);
        myData::MM c;
    }
    /*
        结果:    调用一个参数构造函数
                调用两个参数构造函数
                调用默认构造函数
                @
                A
                B
    */
    return 0;
}