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
$