C++學習筆記(十:類與對象基礎)

往篇內容:

?C++學習筆記(一)
????????一、C++編譯階段※

????????二、入門案例解析?

????????三、命名空間詳解

????????四、C++程序結構

C++學習筆記(二)

????????五、函數基礎

??????? 六、標識符

????????七、數據類型

????????補充:二進制相關的概念

? ? ? ? ? ? ? ? ? sizeof 運算符簡介

????????補充:原碼、反碼和補碼

C++學習筆記(三)

????????補充:ASCII碼表

????????八、內存構成

?????????補充:變量

????????九、指針基礎?

?????? ?十、const關鍵字

????????十一、枚舉類型?

C++學習筆記(四)

????????十二、 類型轉換

????????十三、define指令?

???? ? ?十四、typedef關鍵字

???? ? ?十五、運算符

????????十六、 流程控制

C++學習筆記(六)

? ? ? ? 十七、數組

C++學習筆記(七)

? ? ? ? 十八、指針

C++學習筆記(八)

????????十九、函數進階

? ? ? ? 二十、變量進階

C++學習筆記(九)

? ? ? ? 二十一、結構體

? ? ? ? 二十二、聯合

目錄

二十三、類與對象

1、面向過程

2、面向對象

?3、類

4、對象

5、成員引用

?6、成員函數

?7、inline函數

?8、對象內存

?9、this指針

10、類與結構體的區別?

11、封裝特性?


?

二十三、類與對象

1、面向過程

????????面向過程程序設計(Procedural-Oriented Programming, POP)是一種以過程為中心的編程思想。它強調的是解決問題的步驟和流程,通過函數(或稱為過程)來組織代碼。

????????在 C++ 中,雖然支持 OOP,但仍然兼容傳統的面向過程編程方式,例如使用全局變量、函數等。

思想:先做什么,再做什么,即按照順序執行一系列操作來完成任務。

特點:?

特性描述
程序結構由主函數調用多個函數組成
數據與行為分離數據和操作數據的函數是分開的
順序執行為主強調流程控制,按步驟執行
全局變量常用于共享數據
函數重用可以通過函數復用代碼邏輯

示例:

#include <iostream>
using namespace std;void add(int a, int b) {cout << "Sum: " << a + b << endl;
}int main() {int x = 5, y = 10;add(x, y); // 調用函數return 0;
}

2、面向對象

????????面向對象程序設計(Object-Oriented Programming, OOP)是一種以對象為核心的編程思想。它將現實世界中的事物抽象為對象,每個對象包含數據(屬性)和對數據的操作(方法)。

????????C++ 是一種多范式語言,其中最強大的特性就是對 OOP 的完整支持。

思想:“萬物皆對象,程序由一組相互協作的對象構成,每個對象封裝了自身的狀態和行為

四大核心特性:?

概念描述
封裝(Encapsulation)將數據和操作封裝在一個類中,對外隱藏實現細節
繼承(Inheritance)子類可以繼承父類的屬性和方法,實現代碼復用
多態(Polymorphism)同一個接口可以有多種實現,運行時決定具體行為
抽象(Abstraction)提取共性特征,忽略復雜實現細節

示例:

#include <iostream>
using namespace std;class Rectangle {
private:int width, height;public:Rectangle(int w, int h) : width(w), height(h) {}int area() {return width * height;}
};int main() {Rectangle rect(5, 10);cout << "Area: " << rect.area() << endl;return 0;
}

?3、類

????????類(class是用戶自定義的數據類型,用于封裝數據(屬性)和操作這些數據的方法(行為)。它是面向對象編程(OOP)的核心概念之一。

????????你可以把類看作是藍圖模板,而對象則是根據這個模板創建出來的具體實例。

定義格式:?

class 類名{

????????成員訪問限定符: //private,public,protected三種取值

????????????????[數據成員s];

????????????????[成員函數s];

};

?成員訪問限定符:用來指定個數據成員的訪問屬性

  • public :類內類外都可以訪問
  • private :只能被本類的成員函數引用,類外不能調用(特殊情況后面再討)
  • protected :和private類似,派生時情況不同

注意事項:

  • 成員訪問限定符可以出現多次
  • 作用范圍:從當前限定符到下一個限定符或到類的 }

示例:

class Student {

private:

????????string name;

????????int age;

public:

????????void setName(string n) { name = n; }

????????void setAge(int a) { age = a; }

????????void printInfo() {

????????????????cout << "Name: " << name << ", Age: " << age << endl;

????????}

};

注意事項:?

  • 聲明或定義類類型時不分配內存空間,用類類型實例創建對象時,分配內存空間
  • 不指定成員限定符,默認為 private
  • 定義類對象的方式有3種,與結構體類似
  • 類的成員函數只能由類的對象或指針調用(特殊情況后續討論)

4、對象

  • 客觀世界中任何事物都可以看成對象,對象由屬性和方法組成,每個對象都具有靜態的屬性和動態的功能。
  • 具有相同屬性和功能的對象,我們可以把它們歸為一類,故而我們可以得出結論:類是對象的抽象,對象是類的實例。

抽象概念理解:抽象的過程是將有關事物的共性歸納、集中的過程。

定義對象格式:


class 類名 對象名;

類名 對象名; //推薦

//定義類的同時實例化對象

class 類名{

????????數據成員s;

????????成員函數s;

}對象1,對象2...對象n;

//定義匿名類,同時實例化對象

class {

????????數據成員s;

????????成員函數s;

}對象1,對象2...對象n;

案例:

#include <iostream>
#include <cstring>
using namespace std;// 定義類類型
class Student {// 默認權限修飾符為 private// 成員函數,一般 public
public:void disp() {cout << "id: " << id << endl;cout << "name: " << name << endl;cout << "age: " << age << endl;}// 權限修飾符,一般數據成員 private// private:
public:int id;char name[20];int age;
} s3 = {1020, "lucy", 21}; // 列表初始化依舊有用int main() {// 由類類型實例化對象【定義變量】Student s1;s1.id = 1001;// s1.name = "tom"; error,詳見字符串數組strcpy(s1.name, "tom");s1.age = 20;// 類對象調用成員函數Student s2 = s1; // 修正:刪除了多余的class關鍵字s2.disp();cout << "--------------" << endl;s3.disp();return 0;
}

?注意:對象初始化可以采用列表的方式進行,數據成員不能為private。

5、成員引用

使用類對象調用數據成員或成員函數有2種方式:

  • 對象名.成員名;
  • 類指針變量->成員名;

案例:

#include <iostream>
using namespace std;// 自定義結構體類型
class Student {
public:int num;char name[20];char sex;int age;float score;char addr[30];public:// 成員函數必須通過類對象或指針來調用// 對象名.disp(); 指針變量->disp();void disp() {cout << "Student: [" << num << "," << name << "," << sex<< "," << age << "," << score << "," << addr << "]" << endl;}
};// 值傳遞
void printStudent(Student s) {cout << "Student: " << s.num << "," << s.name << "," << s.sex << "," << s.age << "," << s.score << "," << s.addr << endl;
}// 指針傳遞
void printStudent(Student *p) {cout << "Student: {" << p->num << "," << p->name << "," << p->sex << "," << p->age << "," << p->score << "," << p->addr << "}" << endl;
}// 引用傳遞(注意:不能與值傳遞同名,會產生二義性)
void printStudent2(Student &s) {cout << "Student: (" << s.num << "," << s.name << "," << s.sex << "," << s.age << "," << s.score << "," << s.addr << ")"<< endl;
}int main() {// 初始化Student s = {2001, "Tom", 'M', 19, 78.5, "平遙學院路56號"};printStudent(s);    // 值傳遞printStudent2(s);   // 引用傳遞Student *ps = &s;printStudent(ps);   // 指針傳遞cout << "---------------------" << endl;s.disp();           // 成員函數調用return 0;
}

?6、成員函數

????????類的成員函數(member function是類的重要組成部分之一。它們定義了類的行為,即對象可以執行的操作。

????????它的用法和作用和之前學習的函數基本上是一樣的,也有返回值和函數類型,它與一般函數的區別只是: 它是屬于一個類的成員,出現在類體中。

????????在使用類函數時,要注意調用它的權限 (它能否被調用 )以及它的作用域 (函數能使用什么范圍中的數據和函數 )

成員函數定義方式

① 在類內定義(隱式內聯)

class Circle {

private:

????????double radius;

public:

????????void setRadius(double r) { radius = r; } // 類內定義

????????double getArea() { return 3.14159 * radius * radius; }

};

?? 這種方式適合簡單函數,編譯器會嘗試將其優化為內聯函數 (inline)。

?② 在類外定義(推薦)

class Circle {

private:

????????double radius;

public:

????????void setRadius(double r); // 函數聲明

????????double getArea();

};

// 類外實現

// 返回值類型 類名::函數名(參數列表);

void Circle::setRadius(double r) {

????????radius = r;

}

double Circle::getArea() {

????????return 3.14159 * radius * radius;

}

? 推薦這種方式:代碼更清晰、結構更合理,便于維護。?

注意:

如果函數名前面既無類名又無 ,如 display() display() 這表示 display 函數不屬于任何類,這個函數不是成員函數,而是全局函數,即非成員函數的一般普通函數。

③ 成員函數的調用?

成員函數可以通過對象或指針來調用:

Circle c;

c.setRadius(5.0); // 通過對象調用

c.printInfo();

Circle* pc = &c;

pc->setRadius(10.0); // 通過指針調用

④ const成員函數

如果你希望某個成員函數不修改類成員變量的值,那可以將其聲明為const

class Rectangle {

private:

????????int width, height;

public:

????????int area() const {

????????????????return width * height; // 不允許修改成員變量

}

????????//獲取周長

????????int perimeter() const;

};

//類外定義const函數,一定要跟上const修飾

int Rectangle::perimeter() const

{

????????//width = 2; error

????????return 2 * (width + height);

}

🔒 注意:const 成員函數只能訪問其他 const 成員函數,不能修改任何數據成員。

?7、inline函數

????????為了減少時間開銷,如果在類體中定義的成員函數中不包括循環等控制結構,C++系統會自動將它們作為內聯 inline 函數來處理。

class Circle {

private:

????????double radius;

public:

????????//類內定義,即使沒有inline聲明,默認也為inline函數

????????void setRadius(double r) { radius = r; }

????????double getArea() { return 3.14159 * radius * radius; }

};

在調用 setRadiusgetArea 時,并不真正執行函數調用過程 ,而是將函數代碼嵌入程序的調用點,大大減少了調用成員函數的時間開銷。

注意1:

如果成員函數在類體外定義**,系統并不把它默認為 inline 函數

注意2

如果要在類體外定義 inline 函數,需要在函數定義前加上 inline ,還應類定義和成員函數的定義都放在同一個頭文件中 (或者寫在同一個源文件中),否則編譯時無法進行代碼嵌入。例如:

?//函數定義時加inline,聲明時則不需要

inline void CirclesetRadius(double r)

{

????????radius = r;

}

弊端:上述做法,不利于類的接口與類的實現分離,不利于信息隱蔽。雖然程序的執行效率提高了,但從軟件工程質量的角度來看,這樣做并不是好的辦法。

?8、對象內存

????????用類去定義對象時,系統會為每一個對象分配存儲空間。每個對象占用內存空間大小,只取決于數據成員和對齊方式,和成員函數沒有任何關系。

案例:?

#include <iostream>
#include <cstddef> // for alignof
using namespace std;class MyClass {
public:int x;double y;char z;void disp() {cout << "x: " << x << ", y: " << y << ", z: " << z << endl;}
};int main() {cout << "Alignment of MyClass: " << alignof(MyClass) << " bytes" << endl;cout << "Size of MyClass: " << sizeof(MyClass) << " bytes" << endl;MyClass obj;obj.x = 10;obj.y = 3.14;obj.z = 'A';obj.disp();MyClass obj2;obj2.x = 3;obj2.y = 2.5;obj2.z = 'x';obj2.disp();return 0;
}
思考:為什么調用不同對象成員函數時,執行完全相同的一段函數代碼,但是執行結果是不相同的?

答:因為成員函數可以訪問和操作對象的實例數據(屬性)。每個對象的屬性值是獨立存儲的,因此即使函數代碼相同,執行時基于不同的屬性值會產生不同的結果。

?9、this指針

每個非靜態成員函數都有一個隱藏參數: this ,它是一個指向當前對象的指針。

  • this 是指向調用該函數的對象的指針
  • 常用于解決形參與成員變量同名的問題
  • 可以用來返回當前對象(常用于鏈式調用)

案例:

#include <iostream>
#include <string>  // 補充缺失的頭文件
using namespace std;class MyClass {
public:string name;int x;double y;char z;void disp() {// this指向成員函數的調用者cout << "this: " << this << endl;cout << "name: " << this->name << ", x: " << this->x;cout << ", y: " << this->y << ", z: " << this->z << endl;}void setName(const string& name) {this->name = name;  // 也可以區分同名變量}
};int main() {MyClass c1 = {"zs", 10, 3.14, 'M'};cout << "&c1: " << &c1 << endl;c1.disp();cout << "--------------" << endl;MyClass c2 = {"jack", 20, 2.4, 'F'};cout << "&c2: " << &c2 << endl;c2.disp();return 0;
}

10、類與結構體的區別?

C++增加了class類型后,仍保留了結構體類型(struct), 它不是簡單地繼承 C 的結構體,而是使它也具有類的特點,以便于用于面向對象程序設計。用struct聲明的結構體類型實際上也就是類,兩者區別如下:

  • struct的缺省作用域為public

  • class的缺省作用域為private

11、封裝特性?

類背后蘊含的思想是數據抽象和封裝,兩個重要優點:

  • 避免類內部出現無意的、可能破壞對象狀態的用戶級錯誤
  • 隨時間推移根據需求改變或缺陷報告來完善類實現,而不需要改變用戶級代碼

????????C++通過類實現數據的封裝,將相關的數據與對數據的操作封裝到一個類中。

????????類里面的數據和成員函數通過成員限定符的修飾,改變了這些成員的訪問屬性,實現了信息的隱蔽。

????????在修改代碼時,具體修改某個類,不會對別的類產生影響,方便調試檢查錯誤,這對于大型項目尤為重要。

C++中,封裝通常通過以下方式實現:

  • 使用 private protected 訪問修飾符來限制對類成員的直接訪問
  • 提供公共方法( getter setter )來間接訪問或修改私有成員變量

案例:

class BankAccount {
private:double balance; // 私有成員變量,外部無法直接訪問public:// 構造函數BankAccount(double initialBalance) : balance(initialBalance) {}// Getter 方法double getBalance() const {return balance;}// 存款方法void deposit(double amount) {if (amount > 0) {balance += amount;}}// 取款方法bool withdraw(double amount) {if (balance >= amount && amount > 0) {balance -= amount;return true;}return false;} // 修正:將分號移至此處
}; // 修正:類定義結束符

?????????在這個例子中, balance 變量是私有的,外界不能直接訪問它。相反,提供了 getBalance , deposit withdraw 方法作為與 balance 交互的接口。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90553.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90553.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90553.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

圖片查重從設計到實現(4)圖片向量化存儲-Milvus 單機版部署

Milvus 單機版部署 在 Docker 環境下安裝、應用和配置 Milvus 向量數據庫可以按照以下步驟進行&#xff0c;涵蓋從安裝到基礎應用的完整流程&#xff1a; 1. 部署前準備 服務器&#xff1a;建議測試環境配置 2 核 CPU、8GB 內存&#xff1b;處理 100 萬組向量數據&#xff0c;…

前端版本更新檢測機制

&#x1f4cc; 一、為什么需要前端版本更新檢測機制&#xff1f;在現代 Web 項目中&#xff0c;我們通常會通過 CDN 或緩存策略來加快頁面加載速度&#xff0c;但這也帶來了一個問題&#xff1a;用戶可能訪問的是舊版本的頁面或資源&#xff0c;而不會自動更新到最新版本。這在…

Python(09)正則表達式

特殊字符 1. 基本元字符 .&#xff1a;匹配除換行符以外的任意單個字符。 *&#xff1a;匹配前面的元素零次或多次。 &#xff1a;匹配前面的元素一次或多次。 ?&#xff1a;匹配前面的元素零次或一次。 2. 定量符 {n}&#xff1a;匹配前面的元素恰好 n 次。 {n,}&#xff1a;…

k8s容器放開鎖內存限制

參考&#xff1a;https://access.redhat.com/solutions/1257953 問題 nccl-test容器docker.io/library/nccl-tests:24.12中跑mpirun&#xff0c;buff設置為NCCL_BUFFSIZE503316480 提示out of memory&#xff1a; pod-1:78:91 [0] include/alloc.h:114 NCCL WARN Cuda failure …

基于Zigee的溫度數據采集系統

大家好&#xff0c;本文帶來的是單片機課設-基于Zigee的溫度數據采集系統。 一、設計內容和要求 基于Zigbee的數據采集系統 1.1設計內容 &#xff08;1&#xff09;分析對比Bluetooth、Zigbee、Lora方式組網的基本原理和性能差異&#xff0c;撰寫分析報告&#xff1b; &#xf…

ATH12K 驅動框架分析

文章目錄 Linux Wireless 驅動框架深入分析 **1. 核心框架層次結構** **1.1 cfg80211 子系統 (`net/wireless/`)** **1.2 mac80211 子系統 (`net/mac80211/`)** **2. ath12k 驅動架構分析** **2.1 核心管理文件** **2.2 數據路徑文件** **2.3 平臺接口文件** **2.4 功能模塊文件…

OSPF路由協議單區域

RIP的不足 以跳數評估的路由并非最優路徑 如果RTA選擇S0/0傳輸&#xff0c;傳輸需時會大大縮短為3sRIP協議限制網絡直徑不能超過16跳 收斂速度慢 RIP定期路由更新 – 更新計時器&#xff1a;定期路由更新的時間間隔&#xff0c;默認30秒。 – 失效計時器&#xff1a;失效計時器…

Kubernetes部署與管理Scrapy爬蟲:企業級分布式爬蟲平臺構建指南

引言&#xff1a;Kubernetes在爬蟲領域的戰略價值在大規模數據采集場景中&#xff0c;??容器化爬蟲管理??已成為企業級解決方案的核心。根據2023年爬蟲技術調查報告&#xff1a;采用Kubernetes的爬蟲系統平均資源利用率提升??65%??故障恢復時間從小時級縮短至??秒級?…

Web-Machine-N7靶機攻略

一.環境準備&#xff08;VBox&#xff0c;kali虛擬機&#xff0c;靶機&#xff09; 1.1Vbox下載地址: Downloads – Oracle VirtualBox 1.2將N7導入到這個虛擬機中 1.3將kali和Vbox都設置成橋接模式 1.4開啟靶機 若鼠標出不來可以使用組合技,CtrlAltDelete強制退出 二.信息…

用毫秒級視頻回傳打造穩定操控閉環之遠程平衡控制系統技術實踐

在工業自動化、遠程機器人、無人裝備等復雜作業場景中&#xff0c;遠程實時操控正逐步取代傳統“監控指令”模式&#xff0c;成為提升效率與保障安全的關鍵能力。尤其在高風險、高精度的應用環境中&#xff0c;操作者不僅要“能控”&#xff0c;更要“看得準、反應快”。 真正…

瑞薩電子RA-T MCU系列新成員RA2T1——電機控制專家

RA2T1系列微控制器基于64MHz ArmCortex-M23內核設計&#xff0c;專為單電機控制應用而優化。RA2T1集成PWM定時器&#xff0c;以及配備3個采樣保持電路的A/D轉換器等先進的模擬功能&#xff0c;適用于電動工具&#xff0c;風扇和家用電器等高效的低端電機控制方案。RA2T1支持1.6…

Java排序算法之<選擇排序>

目錄 1、選擇排序 1.1、介紹 1.2、穩定性 2、執行流程 3、java實現 4、優缺點 總結&#xff1a;Java 排序算法進階路線 O(n) 算法&#xff08;適合學習原理&#xff09; 冒泡排序&#xff08;最慢&#xff09;→ 選擇排序 → 插入排序&#xff08;推薦先學&#xff09; …

ESP8266 http收發數據

1.先修改基礎配置 make menuconfig 打開配置菜單 選擇component config 然后選擇 修改波特率為115200 保存退出 2.修改彩色日志打印的 在component config目錄下找到log output 選中點擊空格關掉彩色日志輸出&#xff0c;這樣正常串口打印就沒有亂碼了 然后保存退出 3…

ZLMediaKit 源代碼入門

ZLMediaKit 是一個基于 C11 開發的高性能流媒體服務器框架&#xff0c;支持 RTSP、RTMP、HLS、HTTP-FLV 等協議。以下是源代碼入門的詳細指南&#xff1a; 1. 源碼結構概覽 主要目錄結構&#xff1a; text ZLMediaKit/ ├── cmake/ # CMake 構建配置 ├── …

智能Agent場景實戰指南 Day 21:Agent自主學習與改進機制

【智能Agent場景實戰指南 Day 21】Agent自主學習與改進機制 文章內容 開篇 歡迎來到"智能Agent場景實戰指南"系列的第21天&#xff01;今天我們將深入探討智能Agent的自主學習與改進機制——這是使Agent能夠持續提升性能、適應動態環境的核心能力。在真實業務場景…

微信小程序中英文切換miniprogram-i18n-plus

原生微信小程序使用 miniprogram-i18n-plus第一步&#xff1a;npm install miniprogram-i18n-plus -S安裝完成后&#xff0c;會在項目文件文件夾 node_modules文件里生成 miniprogram-i18n-plus&#xff0c; 然后在工具欄-工具-構建npm&#xff0c;然后看到miniprogram_npm里面…

LeetCode 127:單詞接龍

LeetCode 127&#xff1a;單詞接龍問題本質&#xff1a;最短轉換序列的長度 給定兩個單詞 beginWord 和 endWord&#xff0c;以及字典 wordList&#xff0c;要求找到從 beginWord 到 endWord 的最短轉換序列&#xff08;每次轉換僅改變一個字母&#xff0c;且中間單詞必須在 wo…

docker搭建ray集群

1. 安裝docker 已安裝過docker 沒安裝流程 啟動 Docker 服務&#xff1a; sudo systemctl start docker sudo systemctl enable docker # 設置開機即啟動docker驗證 Docker 是否安裝成功&#xff1a; docker --version2. 部署ray # 先停止docker服務 systemctl stop docker…

【iOS】SideTable

文章目錄前言1??Side Table 的核心作用&#xff1a;擴展對象元數據存儲1.1 傳統對象的內存限制1.2 Side Table 的定位&#xff1a;集中式元數據倉庫2??Side Table 的底層結構與關聯2.1 Side Table 與 isa 指針的關系2.2 Side Table 的存儲結構2.3 SideTable 的工作流程3??…

【Spring Cloud Gateway 實戰系列】高級篇:服務網格集成、安全增強與全鏈路壓測

一、服務網格集成&#xff1a;Gateway與Istio的協同作戰在微服務架構向服務網格演進的過程中&#xff0c;Spring Cloud Gateway可與Istio形成互補——Gateway負責南北向流量&#xff08;客戶端到集群&#xff09;的入口管理&#xff0c;Istio負責東西向流量&#xff08;集群內服…