通过编程练习一,读者能够对析构函数、静态成员、常量成员函数、封闭类及其复制构造函数、const成员和引用成员有比较深入的理解。
析构函数在对象消亡时自动调用,在面向对象编程中起着回收内存空间的作用。
#include
using namespace std;
class CDemo
{
public:
~CDemo() //析构函数
{
cout << "Destructor called" << endl;
}
};
int main()
{
CDemo array[2];//构造函数调用2次
CDemo* pTest = new CDemo;//构造函数调用
delete pTest; //析构函数调用
cout << "----------" << endl;
pTest = new CDemo[2];//构造函数调用2次
delete [] pTest; //析构函数调用2次
cout << "Main ends." << endl;
return 0;
}
函数的参数对象,以及函数的返回值对象,在消亡时会引发析构函数的调用。
#include
using namespace std;
class CDemo
{
public:
~CDemo() { cout << "destructor" << endl; }
};
void Func(CDemo obj)
{
cout << "func" << endl;
}
CDemo d1;
CDemo Test()
{
cout << "test" << endl;
return d1;
}
int main()
{
CDemo d2;
Func(d2);
Test();
cout << "after test" << endl;
return 0;
}
类的对象在生成时构造函数被调用,对象在消亡时析构函数被调用。
#include
using namespace std;
class Demo
{
int id;
public:
Demo(int i)
{
id = i;
cout << "id=" << id << " constructed" << endl;
}
~Demo()
{
cout << "id=" << id << " destructed" << endl;
}
};
Demo d1(1);
void Func()
{
static Demo d2(2);
Demo d3(3);
cout << "func" << endl;
}
int main()
{
Demo d4(4);
d4 = 6;
cout << "main" << endl;
{
Demo d5(5);
}
Func();
cout << "main ends" << endl;
return 0;
}
类的静态成员有两种,分别是静态成员变量和静态成员函数。静态成员变量的本质是全局变量,静态成员函数的本质是全局函数。
#include
using namespace std;
class CRectangle
{
private:
int w, h;
static int totalArea; //矩形总面积
static int totalNumber; //矩形总数
public:
CRectangle(int w_, int h_);
~CRectangle();
static void PrintTotal();
CRectangle(CRectangle& r) {
totalNumber++;
totalArea += r.w * r.h;
w = r.w; h = r.h;
}
};
CRectangle::CRectangle(int w_, int h_)
{
w = w_; h = h_;
totalNumber++; //有对象生成则增加总数
totalArea += w * h;//有对象生成则增加总面积
}
CRectangle::~CRectangle()
{
totalNumber--; //有对象消亡减少总数
totalArea -= w * h;//有对象消亡则减少总面积
}
void CRectangle::PrintTotal()
{
cout << totalNumber << ", " << totalArea << endl;
}
int CRectangle::totalNumber = 0;
int CRectangle::totalArea = 0;
//必须在定义类的文件中对静态成员变量进行一次声明
//或初始化,否则编译能通过,链接不能通过
int main()
{
CRectangle r1(3, 3), r2(2, 2);
CRectangle::PrintTotal();
r1.PrintTotal();
return 0;
}
常量成员函数使用const关键字。
#include
using namespace std;
class Sample {
public:
void GetValue() const;
};
void Sample::GetValue() const
{
cout << "const" << endl;
}
int main()
{
const Sample o;
o.GetValue();//常量对象上可以执行常量成员函数
return 0;
}
常量成员对象上可以调用常量成员函数。
#include
using namespace std;
class CTest {
private:
int n;
public:
CTest() { n = 1; }
int GetValue() const { return n; }
int GetValue() { return 2 * n; }
};
int main() {
const CTest objTest1;
CTest objTest2;
cout << objTest1.GetValue() << ", " << objTest2.GetValue();
cout << endl;
return 0;
}
一个类的成员变量如果是另一个类的对象,那么包含成员对象的类叫做封闭类。
#include
using namespace std;
class CTyre //轮胎类
{
private:
int radius;//半径
int width; //宽度
public:
CTyre(int r, int w) :radius(r), width(w)
{
cout << "CTyre constructor" << endl;
}
~CTyre()
{
cout << "Tyre destructor" << endl;
}
};
class CEngine //引擎类
{
public:
CEngine()
{
cout << "CEngine constructor" << endl;
}
~CEngine()
{
cout << "CEngine destructor" << endl;
}
};
class CCar //汽车类
{
private:
int price; //价格
CTyre tyre;
CEngine engine;
public:
CCar(int p, int tr, int tw);
~CCar()
{
cout << "CCar destructor" << endl;
}
};
CCar::CCar(int p, int tr, int tw) :price(p), tyre(tr, tw)
{
cout << "CCar constructor" << endl;
};
int main()
{
CCar car(20000, 17, 225);
return 0;
}
对于封闭类的复制构造函数,如果封闭类的对象是用默认复制构造函数初始化的,那么成员对象也要用复制构造函数初始化。
#include
using namespace std;
class A
{
public:
A() { cout << "default" << endl; }
A(A& a) { cout << "copy" << endl; }
};
class B
{
A a;
};
int main()
{
B b1, b2(b1);
return 0;
}
常量型成员变量和引用型成员变量,必须在构造函数的初始化列表中进行初始化。
#include
using namespace std;
int f;
class CDemo {
private:
const int num;//常量型成员变量
int& ref; //引用型成员变量
int value;
public:
CDemo(int n) :num(n), ref(f), value(4)
{
}
void PrintCDemo()
{
cout << num << "," << ref << "," << value << endl;
}
};
int main() {
cout << sizeof(CDemo) << endl;
CDemo c(5);
f = 3;
c.PrintCDemo();
return 0;
}
在非静态成员函数内部,可以直接使用this关键字,this代表指向函数所作用对象的指针。
#include
using namespace std;
class A {
public:
int val;
A(int
// 在此处补充你的代码
m = 123):val(m){
}
A& GetObj(){
return *this;
}
};
int main()
{
int m, n;
A a;
cout << a.val << endl;
while (cin >> m >> n) {
a.GetObj() = m;
cout << a.val << endl;
a.GetObj() = A(n);
cout << a.val << endl;
}
return 0;
}