[类和对象]构造和析构

Posted Mr y

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[类和对象]构造和析构相关的知识,希望对你有一定的参考价值。

有关构造函数 

1构造函数定义及调用

  1C++中的类可以定义与类名相同的特殊成员函数,这种与类名相同的成员函数叫做构造函数;

  2)构造函数在定义时可以有参数;

  3)没有任何返回类型的声明。

2构造函数的调用 

  自动调用:一般情况下C++编译器会自动调用构造函数

  手动调用:在一些情况下则需要手工调用构造函数

 

有关析构函数 

析构函数定义及调用

  1C++中的类可以定义一个特殊的成员函数清理对象,这个特殊的成员函数叫做析构函数

    语法:~ClassName()

  2)析构函数没有参数也没有任何返回类型的声明  

  3析构函数在对象销毁自动被调用

  4)析构函数调用机制

    C++编译器自动调用     

          先创建的对象 后释放

 

Q对象销毁是发生在什么时候?

 

A对象的析构函数在的对象销毁前被调用,对象何时销毁也与其作用域有关。

 

例如,全局对象是在程序运行结束时销毁,自动对象是在离开其搜索作用域时销毁,而动态对象则是在使用delete运算符时销毁。

 


 

#include <iostream>
using namespace std;

class Test2
{
public:
//无参数构造函数    
    Test2() 
    {
        m_a = 0;
        m_b = 0;
        cout<<"无参数构造函数"<<endl;
    }

//有参数构造函数  
    Test2(int a)
    {
        m_a = a;
        m_b = 0;
    }

    Test2(int a, int b) 
    {
        m_a = a;
        m_b = b;
        cout<<"有参数构造函数"<<endl;
    }

//赋值构造函数 (copy构造函数) 
    Test2(const Test2& obj)
    {
        cout<<"我也是构造函数 " <<endl;
    }

public:
    void printT()
    {
        cout<<"普通成员函数"<<endl;
    }
    
private:
    int m_a;
    int m_b;
};

int main01()
{    
    Test2 t1;  //调用无参数构造函数
    cout<<"hello..."<<endl;

    return 0;
}



//调用 调用有参数构造函数 3
int main(void)
{
    //1括号法 
    Test2 t1(1, 2);  //调用参数构造函数  c++编译器自动的调用构造函数
    t1.printT();

    // 2 =号法[但这是一个很鸡肋的用法]
    Test2 t2 = (3, 4); // = c++对等号符 功能增强  c++编译器自动的调用构造函数
    
  

    //对象的初始化 和 对象的赋值 是两个不同的概念 
    //3 对象的初始化
    Test2 t4 = Test2(1, 2);  //匿名对象
    t1 =  t4;  //把t4 copy给 t1  //赋值操作
//4 赋值构造函数 (copy构造函数) Test2 t5 = Test2(t1); //等价于Test2 t5(t1); 等价于 Test2 t5 = t1;

//☆ Test2 t5 = Test2(t1);是程序员手工的调用构造函数

cout
<<"hello..."<<endl; return 0; } /*============================================== END File ==============================================*/

 

有参数构造函数
普通成员函数
有参数构造函数
我也是构造函数
hello...


 

赋值构造函数的4种应用场景

这是初始化的两种; Test t2 = t1; Test t2(t1);


第三种是功能函数的形参是一个元素的时候{非指针,非引用},这个时候实参给形参的时候必然调用拷贝构造


第四种是你说的返回,返回一个对象的时候,但这个时候返回的是匿名对象,

  如果是初始化,是直接会转换为要初始化的那个对象的,
  如果是赋值操作,这个时候确实会调用copy构造,但是这个对象的生命周期只有那么一行,用完立即被析构

 

#include <iostream>

using namespace std;

class Test4
{
public:
    Test4()  //无参数构造函数
    {
        m_a = 0;
        m_b = 0;
        cout<<"无参数构造函数"<<endl;
    }

    Test4(int a)
    {
        m_a = a;
        m_b = 0;
    }

    Test4(int a, int b) //有参数构造函数  
    {
        m_a = a;
        m_b = b;
        cout<<"有参数构造函数"<<endl;
    }

    Test4(const Test4& obj )//赋值构造函数 (copy构造函数) 
    {
        cout<<"赋值构造函数 " <<endl;
        m_b = obj.m_b + 100;
        m_a = obj.m_a + 100;
    }                                                                

public:
    void printT()
    {
        cout<<"普通成员函数"<<endl;
        cout<<"m_a"<<m_a<<" m_b"<<m_b<<endl;
    }
private:
    int m_a;
    int m_b;
};


//1  赋值构造函数 用1个对象去初始化另外一个对象  
int main(void)
{
    Test4 t0(1, 2);    
    Test4 t1(1, 2);

    /*赋值操作 和 初始化是两个不同的概念 
        =的赋值操作   不会调用构造函数
        =的初始化操作   会调用构造函数 */ 
    //operator=()//抛砖
    t0 = t1; //用t1 给 t0赋值  

    //第1种调用方法
    Test4 t2 = t1; //用t1来初始化 t2     【one】 
    t2.printT();
    
    //第2种调用方法
    Test4 t3(t1);  //用t1对象 初始化 t2对象   【two】 
    t2.printT();
    
    cout<<"hello..."<<endl;

    return 0;
}

 

 

[Three]

#include <iostream>
using namespace std;


class Location 
{ 
public:
    Location( int xx = 0 , int yy = 0 ) 
    { 
        X = xx ;  Y = yy ;  cout << "None Param Constructor Func.\n" ; 
    }

    //copy构造函数  完成对象的初始化
    Location(const Location & obj) //copy构造函数 
    {
        cout << "Copy Constructor func.\n" ; 
        X = obj.X; 
        Y = obj.Y;
    }
    
    ~Location() 
    { 
        cout << X << "," << Y << " Object destroyed." << endl ; 
    }
    
    int  GetX () { 
        return X ; 
    }
            
    int GetY () { 
        return Y ; 
    }
private:  
    int  X , Y ;
};


//业务函数  形参是一个元素
void f(Location p)
{
    cout<<"业务函数"<<endl;
    cout<<p.GetX()<<endl;
}

void playobj()
{
    Location  a(1, 2);
    Location  b = a;
    cout<<"b对象已经初始化完毕"<<endl;

    f(b); //实参b传给形参p会调用copy构造函数
}

int main()
{
    playobj();
    cout<<"hello..."<<endl;
    return 0;
}

 

None Param Constructor Func.
Copy Constructor func.
b对象已经初始化完毕
Copy Constructor func.
业务函数
1
1,2 Object destroyed.
1,2 Object destroyed.
1,2 Object destroyed.
hello...

 

[Four]

#include <iostream>
#include <cstdio>

using namespace std;


class Location 
{ 
public:
    Location( int xx = 0 , int yy = 0 ) 
    { 
        X = xx ;  Y = yy ;  cout << "Constructor Object.\n" ; 
    }

    //copy构造函数  完成对象的初始化
    Location(const Location & obj) //copy构造函数 
    {
        X = obj.X; Y = obj.Y;
    }
    
    ~Location() 
    { 
        cout << X << "," << Y << " Object destroyed." << endl ; 
    }
    
    int  GetX () { return X ; }        
    
    int  GetY () { return Y ; }
private :   int  X , Y ;
} ;

/******************************************************************************************************************* 
    g函数 返回一个元素 
    结论1 : 函数的返回值是一个元素 (复杂类型的), 返回的是一个新的匿名对象(所以会调用匿名对象类的copy构造函数)
    
    
    结论2: 有关 匿名对象的去和留
    如果用匿名对象  初始化 另外一个同类型的对象, 匿名对象 转成有名对象
    如果用匿名对象  赋值给 另外一个同类型的对象, 匿名对象 被析构
    
    
    你这么写代码,设计编译器的大牛们:
    我就给你返回一个新对象(没有名字 匿名对象)
*******************************************************************************************************************/ 
Location g()
{
    Location A(1, 2);
    return A;
}

//
void objplay2()
{
    g(); 
}

//
void objplay3()
{
    //用匿名对象初始化m 此时c++编译器 直接把匿名对转成m;(扶正) 从匿名转成有名字了m
    Location m = g(); 
    printf("\r\n匿名对象,被扶正,不会析构掉\n");
    cout<<m.GetX()<<endl;
}

void objplay4()
{
    //用匿名对象 赋值给 m2后, 匿名对象被析构
    Location m2(1, 2);
    m2 = g();
    printf("\r\n因为用匿名对象=给m2, 匿名对象,被析构\n");
    cout<<m2.GetX()<<endl;;
}
int main(void)
{
    objplay2();
//    objplay3();
//    objplay4();
    cout<<"hello..."<<endl;

    return 0;
}

 

 

二个特殊的构造函数

1) 默认无参构造函数

    当类中没有定义构造函数时,编译器默认提供一个无参构造函数,并且其函数体为空

2) 默认拷贝构造函数

    当类中没有定义拷贝构造函数时,编译器默认提供一个默认拷贝构造函数,简单的进行成员变量的值复制

 

1)当类中没有定义任何一个构造函数时, c++编译器会提供默认无参构造函数和默认拷贝构造函数
2)当类中定义了拷贝构造函数时, c++编译器不会提供无参数构造函数
3)当类中定义了任意的非拷贝构造函数(即:当类中提供了有参构造函数或无参构造函数), c++编译器不会提供默认无参构造函数
4 )默认拷贝构造函数成员变量简单赋值
总结:只要你写了构造函数,那么你必须用。

 

构造析构阶段性总结
1)构造函数是C++中用于初始化对象状态特殊函数
2)构造函数在对象创建时自动被调用, 在对象离开其作用域时候自动销毁
3)构造函数和普通成员函数都遵循重载规则
4)拷贝构造函数是对象正确初始化的重要保证
5) 必要的时候,必须手工编写拷贝构造函数

 

以上是关于[类和对象]构造和析构的主要内容,如果未能解决你的问题,请参考以下文章

Python--面向对象3大特性&类和对象&类的定义和使用&构造方法和析构方法

基类和派生类中构造函数和析构函数的执行顺序,一图看懂。

《C#零基础入门之百识百例》(四十三)类的构造和析构函数 -- 模拟用户注册

C++类和对象--对象特性

C++入门派生类和基类的构造/析构函数关系

C++类和对象之对象的初始化和清理