1. 程式人生 > >C++之結構體與類

C++之結構體與類

C++中的結構體與類

對比C語言中的結構體

在C語言中,我們經常定義結構體來作為資料結構,而C++也支援定義結構體。C++中的結構體與C語言中的結構體主要有以下幾點區別:

1.C語言需要使用struct structNme來定義結構體,而C++可以直接用structName來定義結構體名。(C語言可通過typedef來為結構體取別名)

#include
<iostream>
using namespace std; struct Point { int x, y; }; int main() { Point p1; p1.x = 1; p1.y = 0; return 1; }

2.C語言中不能初始化結構體成員,而C++中可以

#include <iostream>
using namespace std;
struct Point {
	int x=1, y;
};
int main() {
	Point p1;
	cout << p1.x << endl;
	return
1; }
1

3.C語言中結構體不能有成員函式,而C++中可以有

struct Point {
	int x=1, y;
	void printxy() {
		cout << "x = " << x << endl;
		cout << "y = " << y << endl;
	}
};

4.C語言結構體中不能宣告靜態變數,而C++可以

	struct Point {
		static int x;
	};

5.C語言結構體中的變數不能有訪問修飾符,只能是public,而C++中的可以有

	struct Point {
		private: int x;
	};

6.C語言中結構體不能繼承,而C++中可以

	#include <iostream>
	using namespace std;
	struct Point {
		int x;
	};
	struct Point2D :Point {
		int y;
	};
	int main() {
		Point2D p1;
		p1.x = 1;
		p1.y = 2;
		return 1;
	}

建構函式與解構函式

為什麼需要建構函式

我們知道,對於未初始化的全域性變數,編譯器會自動將其初始化未0;而未初始化的區域性變數,它的值則是未知的。因為全域性變數在程式開始執行之後地址便不會發生改變,因此程式啟動時將其初始化未0不會浪費多少時間。而區域性變數則不同,區域性變數的儲存空間是動態分配的,每次呼叫函式時都可能是不同的,如果每次呼叫該函式都將區域性變數進行初始化,則會帶來許多的時間耗費。因此,未顯式被初始化區域性變數的值是未知的,它的值取決於該地址之前的值。
結構體和物件的初始化則是比變數的初始化更為複雜,結構體和物件中可能含有指標等必須進行初始化的成員,有的可能還涉及到動態記憶體分配等操作。因此,通過定義一個函式來顯式的對結構體或者物件進行初始化是有必要的。我們通過自定義一個成員函式來對結構體進行初始化是一種可行的方式,在每次定義結構體之後都利用該函式對結構體進行初始化即可。但這種方式未免顯得有些麻煩,由於缺少強制性,程式設計師可能會忘記呼叫該函式。因此,C++提供了建構函式,它在結構體或物件定義的時候被自動呼叫來進行初始化

建構函式的特點

建構函式有以下幾個特點:
1.建構函式是一類特殊的成員函式
2.建構函式的名字和結構體/類的名字相同
3.建構函式可以過載
4.如果不編寫建構函式,編譯器會自動生成一個建構函式

下面是一個簡單的例子:

#include <iostream>
using namespace std;
struct Point {
public:
	int x, y;
	Point(int, int);
};
Point::Point(int a, int b) {
	x = a;
	y = b;
}	
int main() {
	Point p1(2,3);
	cout << p1.x << " " << p1.y << endl;
	return 0;
}

上例中為結構體Point定義了建構函式,函式有兩個引數,用於給成員變數賦值。
此建構函式還可以有如下簡單寫法

struct Point {
public:
	int x, y;
	Point(int, int);
};
Point::Point(int a, int b) :x(a), y(b) {}

這裡的x(a), y(b)表示x=a, y=b,還可以進一步簡化為:

struct Point {
public:
	int x, y;
	Point(int a, int b) :x(a), y(b) {};
};

建構函式的過載

建構函式支援過載,它們的名字相同,根據引數列表不同調用不同的建構函式:

struct Point {
public:
	int x, y;
	Point(int a, int b) :x(a), y(b) {};
	Point(int a) :x(a), y(a) {};
};

當使用Point(2)建立結構體時,a=b=2
當使用Point(2, 3)建立結構體時,a=2 b=3

解構函式

另外,C++中還有另一個和建構函式功能相反的函式–解構函式。它的主要作用是釋放資源,清理善後。例子如下:

#include <iostream>
using namespace std;
struct Point {
public:
	int x, y;
	Point(int a, int b) :x(a), y(b) {};
	Point(int a) :x(a), y(a) {};
	~Point() {cout << "Goodbye World" << endl;};
};
int main() {
	Point p1(2, 2);
	cout << p1.x << " " << p1.y << endl;
	return 0;
}
2 2
Goodbye World

上面結構體中的~Point函式為解構函式,在主函式執行完的時候會呼叫這個函式來處理一些善後事宜。這裡自定義了解構函式,於是在程式結束之前會呼叫該解構函式,從而打印出解構函式中的"Goodbye World"。注意解構函式不能過載!

結構體與類的區別

實際上,C++中的結構體與類無太大區別,我們可以通過struct實現class的所有功能。而struct與類最大的區別是預設訪問許可權。

struct的預設訪問許可權為public,而class的預設訪問許可權為private。
下面通過例子說明:

#include <iostream>
#include <string>
using namespace std;
struct Array{
	//結構體預設訪問許可權為public
	int length;
	Array(){};
	void setAge(int Length) { this->length = Length; };
};
class Cat {
	//類預設訪問許可權為private
	int age;
public:
	Cat(){};
	void setAge(int Age) { this->age = Age; };
};
int main() {
	Array a;
	Cat miao;
	a.length = 10;//可以直接賦值
	miao.setAge(10);//可以通過public修飾的成員函式賦值成員變數
	return 0;
}

上面的例子定義了Array結構體和Cat類,Array中的成員變數和成員函式預設訪問許可權為public,而Cat中的預設許可權為private。

為了提高程式的可讀性,我們應該主動設定訪問許可權而不是依靠預設許可權!

在上面這個例子中,我利用結構體來定義陣列,而利用類來定義貓。這顯然可以更好的符合我們的認知,因此我們在選擇使用結構體還是類的時候可以考慮要定義的物件是一種資料結構還是一類事物

總結

(1) C++中的結構體比C語言中的結構體更加的靈活。
(2) C++中的結構體可定義建構函式和解構函式。
(3) C++中的結構體和類的性質與用法大多一致,但成員變數和成員函式的預設訪問許可權不同。
(3) C++中的結構體多用於表示資料結構,而類多用於表示一類事物。