C++分析——常用技巧(一)

C++ 類的構造函數和析構函數

類的析構函數可以用來做簡單的初始化數據,比如爲變量賦值,指針賦NULL,數組和結構體清零等初始化操作。也可以對成員函數進行逗號初始化賦值,構造函數可以進行重載,但析構函數不能。以指針的形式初始化的類在函數結尾要delete指針才能調用到析構函數,而已結構體的形式初始化的類在其作用域結束後自動釋放內存,調用析構函數。
測試使用的類

class Module_CPP
{
public:
        Module_CPP():m_module_a(3),m_module_b(5),pm_module(NULL){};
        Module_CPP(int number);
        Module_CPP(int a,int b);
Module_CPP(const Module_CPP & x);
        ~Module_CPP();
        void Init();

private:    
        int m_module_a;
        int m_module_b;
        char *pm_module;
};

構造函數可以使用傳統函數的形式進行對成員函數的賦值,也可以收冒號的形式進行快速賦值。

測試代碼:

Module_CPP::Module_CPP(int number)
{
        m_module_a = number;
        m_module_b = number * 2;
}

Module_CPP::Module_CPP(int a,int b):m_module_a(a),m_module_b(b),pm_module(NULL)
{

}

Module_CPP::Module_CPP(const Module_CPP & x):m_module_a(x.m_module_b),m_module_b(x.m_module_a)
{
        cout << "copy constructor."<<endl;
}

Module_CPP::~Module_CPP()
{
        m_module_a = 0;
        m_module_b = 0;
        pm_module = NULL;

cout << "APP exit" << endl

}

void Module_CPP::Init()
{
        cout << "m_module_a is " << m_module_a << endl;
        cout << "m_module_b is " << m_module_b << endl;
}

類的初始化與重載

測試方法

    Module_CPP *pModule_1 = new Module_CPP();
    Module_CPP *pModule_2 = new Module_CPP(4);
    Module_CPP Module_1 = Module_CPP(5);

    pModule_1->Init();
    pModule_2->Init();  
    Module_1.Init();

執行結果

$ ./project.o 
m_module_a is 3
m_module_b is 5
m_module_a is 4
m_module_b is 8
m_module_a is 5
m_module_b is 10
APP exit
$

指針的形式申請的類需要在使用結束時釋放內存

    Module_CPP *pModule_1 = new Module_CPP();
    Module_CPP *pModule_2 = new Module_CPP(4);
    Module_CPP Module_1 = Module_CPP(5);

    pModule_1->Init();
    pModule_2->Init();  
    Module_1.Init();

    delete pModule_1;
    delete pModule_2;
    pModule_1 = NULL;
    pModule_2 = NULL;

執行結果

$ ./project.o 
m_module_a is 3
m_module_b is 5
m_module_a is 4
m_module_b is 8
m_module_a is 5
m_module_b is 10
APP exit
APP exit
APP exit
$

複製構造函數

複製構造函數是將原先初始化的類成員函數的值賦值給新的函數
複製構造函數寫法。

//複製構造函數規則可以自定義,此時的m_module_a和m_module_b的值進行了互換
Module_CPP::Module_CPP(const Module_CPP & x):m_module_a(x.m_module_b),m_module_b(x.m_module_a)
{
        cout << "copy constructor."<<endl;
}

使用方法

    Module_CPP Module_1 = Module_CPP(5);
    Module_CPP Module_2 = Module_1;

    Module_1.Init();
    Module_2.Init();

執行結果

$ ./project.o 
copy constructor.
m_module_a is 5
m_module_b is 10
m_module_a is 10
m_module_b is 5
APP exit
APP exit
$

帶參數的成員函數類的構造函數

一個類的成員變量爲這個測試類,若初始化未傳參的話會默認調用Module_CPP();的構造函數。

class CSystem
{
public:
        CSystem();
CSystem(int a,int b);
        ~CSystem();
        void Init();

private:
        Module_CPP  m_module_cpp;
};

若需要將成員變量的類調用帶參的構造函數,則必須在類的構造函數中用冒號的形式賦值。

CSystem::CSystem()
{

}

CSystem::CSystem(int a,int b):m_module_cpp(a,b)
{

}

void CSystem::Init()
{
        m_module_cpp.Init();
}

測試方法:

    CSystem *pSystem_CPP_1 = new CSystem;
    CSystem *pSystem_CPP_2 = new CSystem(12,35);

    pSystem_CPP_1->Init();
    pSystem_CPP_2->Init();

    delete pSystem_CPP_1;
    delete pSystem_CPP_2;
    pSystem_CPP_1 = NULL;
    pSystem_CPP_2 = NULL;

執行結果:

$ ./project.o 
m_module_a is 3
m_module_b is 5
m_module_a is 12
m_module_b is 35
$

C++ 類的重載

類不止是在構造函數重載,最主要的是對方法函數甚至是運算符進行重載。

方法重載

函數方法名相同,但傳入的參數類型或數目不同,進而執行不同的功能,這是C++方法的重載。傳入的參數類型或數目相同,但返回值不同,不是重載,違反因果關係,無法編譯通過。

重載的方法函數

class Module_CPP
{
public:
        Module_CPP();
        ~Module_CPP();

        void Module_Func();
        void Module_Func(int a);
        void Module_Func(char a);
        void Module_Func(int a,int b);
        void Module_Func_Run();
}

重載方法函數:

void Module_CPP::Module_Func()
{
        cout << __func__ << " is called." << endl;
}

void Module_CPP::Module_Func(int a)
{
        cout << __func__ << " is called. a is " << a << endl;
}

void Module_CPP::Module_Func(char a)
{
        cout << __func__ << " is called. a is " << a << endl;
}

void Module_CPP::Module_Func(int a,int b)
{
        cout << __func__ << " is called. a is " << a;
        cout << " b is " << b << endl;
}

運行方法:

    Module_CPP *pModule = new Module_CPP();

    pModule->Module_Func();
    pModule->Module_Func(4);
    pModule->Module_Func('z');
    pModule->Module_Func(5,8);

    delete pModule;
    pModule = NULL;

執行結果:

$ ./project.o 
Module_Func is called.
Module_Func is called. a is 4
Module_Func is called. a is z
Module_Func is called. a is 5 b is 8
APP exit
$

運算符重載

運算符重載後不會改變其優先級關係,幾乎所有的運算符都可以重載,只有以下幾個運算符不能進行重載:成員運算符“.”、作用域運算符“::”、長度計算運算符“sizeof”、條件運算符“?:”以及強轉運算符static_cast、const_cast、reinterpret_cast、dynamic_cast。

運算符重載可以自己定義重載規則,返回值可以是整數,也可以是一個類。

運算符重載調用

示例源碼:

class Test_operator
{
public:
    Test_operator():x(0),y(0){}
    Test_operator(int a,int b):x(a),y(b){}
    ~Test_operator(){x = 0;y = 0;}
    int Read_Value_x(){return x;}
    int Read_Value_y(){return y;}
    int operator*(const Test_operator &S)
    {
        return (this->x * S.x) + (this->y * S.y);
    }

    Test_operator operator+(const Test_operator &S)
    {
        Test_operator S1;
        S1.x = this->x + S.x;
        S1.y = this->y + S.y;

        return S1;
    }
    Test_operator &operator<<(const int a)
    {
        this->x += a;
        this->y += a * a;

        return *this;
    }

private:
    int x;
    int y;  
};

測試代碼:

    Test_operator Test1(2,5);
    Test_operator Test2(7,9);

    cout << "Test1 * Test2 = " << Test1 * Test2 << endl;

    Test1 << 3;
    Test2 << 5 << 7;
    cout << "Test1 x = " << Test1.Read_Value_x() << " y = " << Test1.Read_Value_y() << endl;
    cout << "Test2 x = " << Test2.Read_Value_x() << " y = " << Test2.Read_Value_y() << endl;

    Test_operator Test3 = Test1 + Test2;
    cout << "Test3 x = " << Test3.Read_Value_x() << " y = " << Test3.Read_Value_y() << endl;

    Test3 = Test1 + Test2 + Test3;
    cout << "Test3 x = " << Test3.Read_Value_x() << " y = " << Test3.Read_Value_y() << endl;

執行結果:

Test1 * Test2 = 59          // 59 = 2*7+5*9
Test1 x = 5 y = 14          // x=5=2+3          y=14=5+3*3
Test2 x = 19 y = 83         // x=19=7+5+7       y=83=9+5*5+7*7
Test3 x = 24 y = 97         // x=24=5+19        y=97=14+83
Test3 x = 48 y = 194        // x=48=5+19+24 y=194=14+83+97

類調用父類運算符

繼承基類時,如果父類有運算符重載,子類需要調用父類的運算符操作

繼承類

class Coperator : public Test_operator
{
public:
        Coperator(){}
        Coperator(int x,int y):Test_operator(x,y){}
        ~Coperator(){}

        void Module_Value_add(Test_operator &value);
};

void Coperator::Module_Value_add(Test_operator &value)
{
        Test_operator TestValue = operator+(value); //調用繼承的運算符重載

        cout << "TestValue x = " << TestValue.Read_Value_x() << " y = " << TestValue.Read_Value_y() << endl;
}

測試代碼

Test_operator   Test1(2,5);
    Coperator   TestCoperator(6,7);

    TestCoperator.Module_Value_add(Test1);

執行結果

./project.o 
TestValue x = 8 y = 12

C++ 類的內聯函數 inline

類的內聯函數代替C語言中的宏定義作用,若代碼執行時間很短,則將函數定義爲內聯函數,節省調用時間。
在函數前面加上內聯函數的關鍵字inline,該函數則爲內聯函數,在頭文件的聲明中直接實現方法函數,其本身自動就成爲內聯函數。

內聯函數測試類定義。

class Test_inline
{
public:
    Test_inline(int a,int b):m_a(a),m_b(b){}        
    virtual ~Test_inline()
    {
        m_a = 0;
        m_b = 0;
    }

    int Min()           //直接在聲明中定義方法其實就是內聯函數,等價於inline int Min()
    {
        return m_a < m_b ? m_a : m_b;
    }   
    inline int Max()        //也可以強制加上內聯函數關鍵字inline
    {
        return m_a > m_b ? m_a : m_b;
    }

private:
    int m_a;
    int m_b;
};

示例代碼:

    Test_inline *p = new Test_inline(6,9);
    cout << "Max is " << p->Max() << endl;
    cout << "Min is " << p->Min() << endl;

    delete p;
    p = NULL;   

執行結果:

$ ./project.o 
Max is 9
Min is 6
$
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章