C++ 物件導向 一

mug發表於2021-09-09

C++ 物件導向

c++建立物件的時候如果使用new運算子,將會返回返回一個指標,指向堆中的記憶體地址

類,物件

類定義

定義一個類,用來描述一個盒子

#include <iostream>

using namespace std;

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
};

int main(){
	return 0;
}

public 表明這是一個公共的成員。class定義一個類

定義物件

#include <iostream>

using namespace std;

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
};

int main(){
	Box box1;	// 宣告一個物件
	Box box2; // 宣告一個物件

	return 0;
}
#include <iostream>

using namespace std;

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
};

int main(){
	Box box1;	// 宣告一個物件
	Box box2; // 宣告一個物件
	double volume = 0.0;	// 定義一個儲存體積的

	// 第一個盒子
	box1.length = 5.0;
	box1.breadth = 7.0;	
	box1.height = 5.0;

	// 第二個盒子
	box2.length = 10.0;
	box2.breadth = 10.0;
	box2.height = 10.0;

	// 第一個盒子的體積
	volume = box1.length * box1.breadth * box1.height;
	cout << "第一個盒子的體積" << volume << endl;

	// 第二個盒子的體積
	volume = box2.length * box2.breadth * box2.height;
	cout << "第二個盒子的體積" << volume << endl;

	return 0;
}

類和函式成員

類可以為函式成員。

#include <iostream>

using namespace std;

int getVolume(void){
	return 3;
}

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
			double getVolume(void);	// 呼叫函式,將會返回體積。
};

int main(){
	
	return 0;
}
#include <iostream>

using namespace std;

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
			double getVolume(void){
				return length * breadth * height;
			}
};

int main(){
	
	return 0;
}

範圍解析運算子

訪問解析運算子為:: 說明函式屬於哪個類
範圍解析運算子指明函式屬於哪個類,標明作用域。

#include <iostream>

using namespace std;

int year;	// 定義一個全域性變數

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
			double getVolume(void){
				return length * breadth * height;
			}
};

void setYear(int year){
	::year = year;	// 指向全域性變數
}

int main(){
	
	return 0;
}

在類的外部標明類的成員

#include <iostream>

using namespace std;

int year;	// 定義一個全域性變數

class Box {
	public: double length;	// 定義長度
			double breadth;	// 定義寬度
			double height;	// 定義高度
			double getVolume(void){
				return length * breadth * height;
			}
};

void setYear(int year){
	::year = year;	// 指向全域性變數
}

double Box::getLength(void){
	return length;	// 此處返回的是Box類下的getLength變數
}

int main(){
	
	return 0;
}

關於inline

解決小函式頻繁入棧,出棧的問題,引入inline關鍵字。
即,行內函數。
使用行內函數的時候,編譯器會進行自動替換,即類似於C語言中的宏。以減少入棧和出棧的操作。

這是建議,是否取決於編譯器

使用inline的時候,建議在h檔案中,需要的時候寫inline

關於虛擬函式

虛擬函式,用來實現多重繼承和多型。
這個後期在說

類訪問修飾符

資料的封裝為物件導向的特點。
防止函式直接訪問類的內部成員。
作用域為一個大花括號

public成員

public在外部可以訪問

#include <iostream>

using namespace std;

class Line{
public:
	double length;
	void setLength(double len);	// 設定length
	double getLength(void);	// 獲取length
}

// 對成員函式進行定義
double Line::getLength(void){
	return length;
}

void Line::setLength(double len){
	length = len;
}

// 主函式
int main(){
	Line line;

	// 設定長度
	line.setLength(6.0);
	cout << line.getLength() << endl;

	// 設定長度
	line.length = 10.0;
	cout << line.length << endl;

	return 0;
}

private 成員

即私有成員,在外部無法訪問

預設值為private 私有的

protected 保護成員

和私有成員類似,最大的不同在於在子類中仍然可以訪問。

建構函式 解構函式

建構函式

建立物件的時候會執行建構函式

#include <iostream>

using namespace std;

class Line{
public:
	void setLength(double len);
	double getLength(void);
	Line();	// 建構函式

private:	// 私有
	double length;
};

// 成員函式定義
Line::Line(void)
{
    cout << "Object is being created" << endl;
}

void Line::setLength(double len){
	length = len;
}

double Line::getLength(void){
	return length;
}

// 程式主函式
int main(){
	Line line;

	// 設定長度
	line.setLength(6.0);
	cout << line.getLength() << endl;

	return 0;
}

解構函式

類的特殊成員函式,每次刪除建立的物件將會執行解構函式

java中是直接將指向設定為null,即可自動進行清除

#include <iostream>

using namespace std;

class Line{
public:
	void setLength(double len);
	double getLength(void);
	Line();	// 建構函式
	~Line();	// 解構函式

private:	// 私有
	double length;
};

// 成員函式定義
Line::Line(void)
{
    cout << "Object is being created" << endl;
}

Line::~Line(){
	cout << "Object is being deleted" << endl;
}

void Line::setLength(double len){
	length = len;
}

double Line::getLength(void){
	return length;
}

// 程式主函式
int main(){
	Line* line = new Line();

	// 設定長度
	line->setLength(6.0);
	cout << line->getLength() << endl;

	delete line;

	return 0;
}

建構函式初始化列表

#include <iostream>

using namespace std;

class Line{
public:
	void setLength(double len);
	double getLength(void);
	Line();	// 建構函式
	~Line();	// 解構函式

private:	// 私有
	double length;
};

// 成員函式定義
Line::Line(void):length(3)	// 等價於內部定義 length = 3
{
    cout << "Object is being created" << endl;
}

Line::~Line(){
	cout << "Object is being deleted" << endl;
}

void Line::setLength(double len){
	length = len;
}

double Line::getLength(void){
	return length;
}

// 程式主函式
int main(){
	Line* line = new Line();

	// 設定長度
	line->setLength(6.0);
	cout << line->getLength() << endl;

	delete line;

	return 0;
}

需要注意的是,宣告的時候是按照宣告的順序進行初始化的,而不是根據初始化列表進行初始化的

複製建構函式

一種特殊的建構函式。

這裡會涉及到深複製和淺複製的問題,深複製開闢空間,淺複製進行引用

使用的場景
把物件傳入函式
將物件返回函式
深複製,淺複製,即使用同型別的物件初始化一個新的物件

類中有指標變數,動態記憶體分配的時候,必須設定一個複製建構函式,如果沒有編譯器會自動生成複製建構函式

#include <iostream>

using namespace std;

class Line{
public:
	int getLength(void);
	void setLength(int length);
	Line(int len);
	Line(const Line &obj);	// 複製建構函式 傳入的是地址
	~Line();

private:
	int* ptr;	// 定義一個空指標
};

// 設定成員函式,以及建構函式
Line::Line(int len){
	cout << "呼叫建構函式" << endl;
	// 進行記憶體分配
	ptr = new int;	// 在堆中建立記憶體空間,完成指向
	*ptr = len;	// 將傳入的內容進行復制到新開闢在堆中的記憶體空間
}

Line::Line(const Line &obj){
	cout << "呼叫複製建構函式併為指標ptr分配記憶體,即完成深複製" << endl;
	ptr = new int;	// 重新開闢出一塊新的記憶體空間,完成深複製
	*ptr = *obj.ptr;	// 將待複製的,進行內容的賦值
}

Line::~Line(void){	// 解構函式
	cout << "釋放記憶體" << endl;
	delete ptr;	// 將指標刪除,此時在堆中的一併刪除
}
int Line::getLength(void){
	return *ptr;	// 返回指向堆中int的內容
}
void Line::setLength(int length){
	*ptr = length;
}

void display(Line obj){	// 傳入一個物件	建立了一個副本,此時有兩份記憶體。同時儲存著obj
	cout << "line 大小:" << obj.getLength() << endl;
	// 進行賦值
	obj.setLength(3);
	cout << "line 大小:" << obj.getLength() << endl;
}
// 主函式
int main(){
	// 進行複製初始化
	Line line1(10);
	//Line line3 = line1;

	Line line2 = line1;	// 呼叫複製建構函式,建立了一塊新的空間

	display(line1);
	display(line2);

	cout << line1.getLength() << endl;

	line1.setLength(4);
	cout << line1.getLength() << endl;
	return 0;
}

友元函式

友元函式定義在外部,但是有權訪問內部成員。
需要在原型中使用friend關鍵字

#include <iostream>

using namespace std;

class Box{
    double width;	// 預設值為私有的
public:
    friend void printWidth(Box box);	// 定義友元函式,友元函式沒有this指標
    void setWidth(double wid);
};

// 成員函式定義
void Box::setWidth(double wid){
    width = wid;
}

// 友元函式不是任何類的成員函式
void printWidth(Box box){
    // 友元函式可以訪問類中的任何成員
    cout << "width of box" << box.width << endl;
}

int main(){
    Box* box = new Box();

    // 使用成員函式設定寬度
    box -> setWidth(10.0);

    // 使用友元函式輸出寬度
    printWidth(*box);

    return 0;
}

this指標

每一個物件可以透過this指標訪問自己的地址。

#include <iostream>

using namespace std;

class Box{
public:
    // 建構函式定義
    Box(double l = 2.0, double b = 2.0, double h = 2.0){
        cout << "開始輸出值" << endl;
        length = 1;
        breadth = b;
        height = h;
    }
    double Volume(){
        return length * breadth * height;
    }
    int compare(Box box){
        return this -> Volume() > box.Volume();	// this指向呼叫的物件,返回一個布林值
    }
private:
    double length;
    double breadth;
    double height;
};

int main(void){
    Box Box1(3.3, 1.2, 1.5);
    Box Box2(8.5, 6.0, 2.0);

    cout << Box1.compare(Box2) << endl;

    return 0;
}

類的靜態成員

使用static關鍵字
常用於定義工具函式
靜態成員函式,沒有this指標,只能訪問靜態成員。
普通成員有this指標,可以訪問類中的任意成員,靜態成員函式沒有this指標。
初始化使用


int Box::objectCount = 0;

至於為什麼要在外面定義,因為要進行分配記憶體空間。
而類僅僅是定義。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/506/viewspace-2815607/,如需轉載,請註明出處,否則將追究法律責任。

相關文章