1. 程式人生 > >C++ 面向物件 一

C++ 面向物件 一

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
https://openhome.cc/Gossip/CppGossip/inlineFunction.html

關於虛擬函式

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

類訪問修飾符

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

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;

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