天天看點

C++學習(資料的共享與保護)

對象的生存期

1、靜态生存期

• 這種生存期與程式的運作期相同。

• 在檔案作用域中聲明的對象具有這種生存期。

• 在函數内部聲明靜态生存期對象,要冠以關鍵字

static。

2、動态生存期

• 塊作用域中聲明的,沒有用static修飾的對象是動态生存期的對象(習慣稱局部生存期對象)。

• 開始于程式執行到聲明點時,結束于命名該辨別符的作用域結束處。

#include <iostream>
using namespace std;

int i = 1;//i為全局變量,具有靜态生存期

void other(){
	static int a = 3;
	static int b;
	//a,b為靜态局部變量,具有全局壽命,局部可見
	//隻第一次進入函數時被初始化
	int c = 10;//局部變量,具有動态生存期,每次進入函數時都被初始化
	a += 2; i += 32; c += 5;
	cout << "---Other---\n";
	cout << "i: " << i << "a: " << a << "b: " << b << "c: " << c << endl;
	b = a;
}

int main(){
	static int a;//靜态局部變量,有全局壽命,局部可見。
	int b = -10; // b, c為局部變量,具有動态生存期。
	int c = 0;
	cout << "‐‐‐MAIN‐‐‐\n";
	cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
	c += 8; other();
	cout<<"‐‐‐MAIN‐‐‐\n";
	cout<<" i: "<<i<<" a: "<<a<<" b: "<<b<<" c: "<<c<<endl;
	i += 10; other();

	system("pause");
	return 0;
}
           

運作結果

C++學習(資料的共享與保護)

類的靜态成員

1、靜态資料成員

▫ 用關鍵字static聲明

▫ 該類的所有對象維護該成員的同一個拷貝,靜态資料成員具有靜态生存期。

▫ 必須在類外定義和初始化,用(::)來指明所屬的類。

#include <iostream>
using namespace std;
class Point { //Point類定義
public: //外部接口
	Point(int x = 0, int y = 0) : x(x), y(y) { //構造函數
		//在構造函數中對count累加,所有對象共同維護同一個count
		count++;
	}
	Point(Point &p) {//拷貝構造函數
		x = p.x;
		y = p.y;
		count++;
	}
	~Point() { count--; }
	int getX() { return x; }
	int getY() { return y; }

	void showCount() { //輸出靜态資料成員
		cout << " Object count = " << count << endl;
	}
private: //私有資料成員
	int x, y;
	static int count;//靜态資料成員聲明,用于記錄點的個數
};

int Point::count = 0;//靜态資料成員定義和初始化,使用類名限定

int main() {//主函數
	Point a(4, 5); //定義對象a,其構造函數回使count增1
	cout << "Point A: " << a.getX() << ", " << a.getY();
	a.showCount(); //輸出對象個數
	Point b(a); //定義對象b,其構造函數回使count增1
	cout << "Point B: " << b.getX() << ", " << b.getY();
	b.showCount(); //輸出對象個數

	system("pause");
	return 0;
}
           

運作結果

C++學習(資料的共享與保護)

2、靜态函數成員

▫ 類外代碼可以使用類名和作用域操作符來調用靜态成員函數。

▫ 靜态成員函數隻能引用屬于該類的靜态資料成員或靜态成員函數。

#include <iostream>
using namespace std;
class Point { //Point類定義
public: //外部接口
	Point(int x = 0, int y = 0) : x(x), y(y) { //構造函數
		//在構造函數中對count累加,所有對象共同維護同一個count
		count++;
	}
	Point(Point &p) { //拷貝構造函數
		x = p.x;
		y = p.y;
		count++;
	}
	~Point() { count--; }
	int getX() { return x; }
	int getY() { return y; }
    static void showCount() { //靜态函數成員
		cout << " Object count = " << count << endl;
	}

private: //私有資料成員
	int x, y;
	static int count;//靜态資料成員聲明,用于記錄點的個數
};
int Point::count = 0;//靜态資料成員定義和初始化,使用類名限定
int main() {//主函數
	Point a(4, 5); //定義對象a,其構造函數回使count增1
	cout << "Point A: " << a.getX() << ", " << a.getY();
	Point::showCount(); //輸出對象個數
	Point b(a); //定義對象b,其構造函數回使count增1
	cout << "Point B: " << b.getX() << ", " << b.getY();
	Point::showCount(); //輸出對象個數

	system("pause");
	return 0;
}
           

(注意對比之前的代碼,主要關注靜态函數的調用方式與靜态函數隻能調用靜态資料成員)

類的友元

• 友元是C++提供的一種破壞資料封裝和資料隐藏的機制。

• 通過将一個子產品聲明為另一個子產品的友元,一個子產品能夠引用到另一個子產品中本是被隐藏的資訊。

• 可以使用友元函數和友元類。

• 為了確定資料的完整性,及資料封裝與隐藏的原則,建議盡量不使用或少使用友元。

1、友元函數

• 友元函數是在類聲明中由關鍵字friend修飾說明的非成員函數,在它的函數體中能夠通過對象名通路private 和protected成員

• 作用:增加靈活性,使程式員可以在封裝和快速性方面做合理選擇。

• 通路對象中的成員必須通過對象名。

#include <iostream>
#include <cmath>
class Point { //Point類聲明
public: //外部接口
	Point(int x=0, int y=0) : x(x), y(y) { }
	int getX() { return x; }
	int getY() { return y; }
	friend float dist(Point &a, Point &b);
private: //私有資料成員
	int x, y;
};

float dist( Point& a, Point& b) {
	double x = a.x ‐ b.x;
	double y = a.y ‐ b.y;
	return static_cast<float>(sqrt(x * x + y *
y));
}
int main() {
	Point p1(1, 1), p2(4, 5);
	cout <<"The distance is: ";
	cout << dist(p1, p2) << endl;
	return 0;
}
           

2、友元類

• 若一個類為另一個類的友元,則此類的所有成員都能通路對方類的私有成員。

• 聲明文法:将友元類名在另一個類中使用friend修飾說明。

友元關系是單向的

如果聲明B類是A類的友元,B類的成員函數就可以通路A類的私有和保護資料,但A類的成員函數卻不能通路B類的私有、保護資料。

共享資料的保護

1、常對象:常類型的對象必須進行初始化,而且不能被更新。

• 常對象:必須進行初始化,不能被更新。

const 類名 對象名

• 常引用:被引用的對象不能被更新。

const 類型說明符 &引用名

• 常數組:數組元素不能被更新。

類型說明符 const 數組名[大小]…

• 常指針:指向常量的指針。

2、用const修飾的對象成員

• 常成員函數

▫ 使用const關鍵字說明的函數。

▫ 常成員函數不更新對象的資料成員。

▫ 常成員函數說明格式:

類型說明符函數名(參數表)const;

這裡,const是函數類型的一個組成部分,是以在實作部分也要帶const關鍵字。

▫ const關鍵字可以被用于參與對重載函數的區分

• 通過常對象隻能調用它的常成員函數。

• 常資料成員

▫ 使用const說明的資料成員。

3、常引用

• 如果在聲明引用時用const修飾,被聲明的引用就是常引用。

• 常引用所引用的對象不能被更新。

• 如果用常引用做形參,便不會意外地發生對實參的更改。常引用的聲明形式如下:

▫ const 類型說明符&引用名;

float dist(const Point &p1, const Point &p2) {
	double x = p1.x ‐ p2.x;
	double y = p1.y ‐ p2.y;
	return static_cast<float>(sqrt(x * x + y *
	y));
           

補充

外部變量與外部函數

• 如果一個變量除了在定義它的源檔案中可以使用外,還能被其它檔案使用,那麼就稱這個變量是外部變量。

• 檔案作用域中定義的變量,預設情況下都是外部變量,但在其它檔案中如果需要使用這一變量,需要用extern關鍵字加以聲明。

• 在所有類之外聲明的函數(也就是非成員函數),都是具有檔案作用域的。

• 這樣的函數都可以在不同的編譯單元中被調用,隻要在調用之前進行引用性聲明(即聲明函數原型)即可。也可以在聲明函數原型或定義函數時用extern修飾,其效果與不加修飾的預設狀态是一樣的。

編譯預處理

• #include 包含指令

▫ 将一個源檔案嵌入到目前源檔案中該點處。

▫ #include<檔案名>

 按标準方式搜尋,檔案位于C++系統目錄的include子目錄下

▫ #include"檔案名"

 首先在目前目錄中搜尋,若沒有,再按标準方式搜尋。

• #define 宏定義指令

▫ 定義符号常量,很多情況下已被const定義語句取代。

▫ 定義帶參數宏,已被内聯函數取代。

• #undef

▫ 删除由#define定義的宏,使之不再起作用。

繼續閱讀