C++類和對象初識

  • 面向過程
    1.1 面向過程特點
    1.2 通俗解釋:煮方便面
    1.3 面向過程實現代碼
    1.4 特點總結

  • 面向對象
    2.1 面向對象特點
    2.2 通俗解釋:對象協作思維
    2.3 面向對象實現代碼
    2.4 特點總結

  • 面向對象和面向過程總結

  • C++ 面向對象介紹
    4.1 面向對象三大基本特征

    • 封裝(Encapsulation)

    • 繼承(Inheritance)

    • 多態(Polymorphism)
      4.2 三大特征的通俗解釋

  • C++ 類與對象初識
    5.1 類的定義
    5.2 類的對象
    5.3 類的訪問控制與封裝
    5.4 類的成員函數

    • 聲明與實現都放在 .h 文件中

    • 聲明放在 .h 文件,定義放在 .cpp 文件

  • 總結

面向過程和面向對象

面向過程

核心是強調過程/步驟,程序就是一系列函數和語句的組合,把問題分解為一系列步驟(函數),數據在函數間傳遞

面向過程特點:

  1. 以函數為中心: 函數是主要的組織單位
  2. 數據與函數分離:數據結構獨立存在,函數對數據進行操作
  3. 自頂向下設計:先規劃整體流程,再逐步細化
  4. 適合小型程序:邏輯簡單,編寫快速

面向對象

強調對象,程序由對象組成,對象封裝了數據(屬性)和行為(方法),面向對象是通過模擬現實世界中的事物和關系來解決問題

面向對象特點:

  1. 以對象為中心: 對象是基本單位
  2. 數據與方法封裝:對象內部隱藏實現細節,通過接口與外部交互
  3. 三大特性:封裝(Encapsulation)、繼承(Inheritance)、多態(Polymorphism
  4. 適合大型復雜系統:可擴展,可復用,可維護

通俗解釋

煮方便面為例對比面向過程面向對象

面向過程:
思維方式: 一步步按流程來做

  1. 燒開水
  2. 打開調料包倒進碗里
  3. 把面餅放進開水煮熟
  4. 把面和湯放進碗里
  5. 等待一下,就可以吃了
    這里每個動作就是一個"函數/步驟",整個煮面過程就是把這些步驟順序執行

面向過程實現代碼:

#include <iostream>
#include <thread>
#include <chrono> // 用于等待
using namespace std;
// 步驟 1: 燒開水
void boilWater() {cout << "正在燒開水..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "水已經燒開了。" << endl;
}
// 步驟 2: 打開調料包倒進碗里
void addSeasoning() {cout << "打開調料包,倒進碗里。" << endl;
}
// 步驟 3: 把面餅放進開水煮熟
void cookNoodles() {cout << "把面餅放進開水里煮..." << endl;this_thread::sleep_for(chrono::seconds(2));cout << "面已經煮熟了。" << endl;
}
// 步驟 4: 把面和湯放進碗里
void serveNoodles() {cout << "把面和湯一起倒進碗里。" << endl;
}
// 步驟 5: 等待一下,就可以吃了
void waitAndEat() {cout << "等待冷卻一下..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "可以開動啦!" << endl;
}
int main() {boilWater();addSeasoning();cookNoodles();serveNoodles();waitAndEat();return 0;
}

特點:

  • 以"過程為主"
  • 如果要換成"煮餃子",要重新寫一套步驟
  • 不強調"面"本身的特性,只關心動作順序


    面向對象:
    思維方式:把事物抽象成對象
  • 有一個水壺對象,它有屬性: 容量,水溫,有方法: 燒水()
  • 有一個面對象,它有屬性:面餅大小,口味,有方法: 煮()
  • 有一個調料對象,它有方法: 添加()
  • 有一個人對象,他只需要調用
person.做飯(面, 水壺, 調料)

只要調用對象的方法,就能完成煮面

這里強調的是對象之間的協作,而不是具體的步驟細節

面向對象實現代碼

#include <iostream>
#include <thread>
#include <chrono>using namespace std;// 水壺對象
class Kettle {
public:void boilWater() {cout << "水壺開始燒水..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "水壺燒開了水。" << endl;}
};// 調料對象
class Seasoning {
public:void addToBowl() {cout << "調料包已倒入碗中。" << endl;}
};// 面對象
class Noodle {
public:void cook() {cout << "面餅放進開水中煮..." << endl;this_thread::sleep_for(chrono::seconds(2));cout << "面已經煮熟了。" << endl;}
};// 人對象
class Person {
public:void cookNoodles(Kettle& kettle, Seasoning& seasoning, Noodle& noodle) {kettle.boilWater();   // 調用水壺的方法seasoning.addToBowl(); // 調用調料的方法noodle.cook();        // 調用面的煮方法cout << "把面和湯一起倒進碗里。" << endl;cout << "等待冷卻一下..." << endl;this_thread::sleep_for(chrono::seconds(1));cout << "可以開動啦!" << endl;}
};int main() {Kettle kettle;Seasoning seasoning;Noodle noodle;Person person;person.cookNoodles(kettle, seasoning, noodle);return 0;
}

特點:

  • 以"對象"為主
  • 如果換成"煮餃子",只需要定義一個餃子對象,人對象調用==做飯(餃子,水壺,調料)==就行
  • 強調復用性和擴展性

面向對象和面向過程總結

面向過程是一種以步驟和函數為核心的編程思想,強調“怎么做”,適合小型、邏輯清晰的程序;而面向對象則以對象及其屬性和行為為核心,強調“誰來做”,通過封裝、繼承和多態實現更好的復用與擴展,適合構建大型、復雜、可維護的系統

c++面向對象介紹

C++ 面向對象(OOP, Object-Oriented Programming)是一種程序設計思想,它將現實世界中的事物抽象成“對象”,通過對象之間的交互來完成程序功能。C++ 在 C 的基礎上引入了類(class)和對象(object),使得它既支持面向過程(POP),又支持面向對象。

面向對象三大基本特征

C++ 面向對象的核心特性是 封裝、繼承、多態

  • 封裝
    • 把數據(成員變量)和操作數據的函數(成員函數)封裝到類中,形成一個整體。
    • 提供 public / private / protected 訪問權限,保證數據安全。
    • 舉例:銀行卡類,余額是私有的,必須通過 取錢()存錢() 方法來訪問。
  • 繼承
    • 一個類可以繼承另一個類的成員(變量和方法)。
    • 允許代碼復用,同時可以擴展功能
    • 舉例:學生類 繼承 人類,就自動擁有了姓名、年齡屬性,還可以擴展為學號、成績。
  • 多態
    • 相同的操作針對不同對象有不同的表現。
    • 分為 靜態多態(函數重載、運算符重載)和 動態多態(虛函數 + 基類指針/引用)。
    • 舉例:動物 類有一個 speak() 方法, 調用時輸出“汪汪”, 調用時輸出“喵喵”。

面向對象三大基本特征的通俗解釋

封裝就像一個自動售貨機,你只需要按按鈕投幣(調用接口),不需要知道機器內部怎么找零,怎么調貨(內部實現被隱藏),在編程里,封裝就是把數據和操作打包起來,只暴露需要的部分可以保護數據安全,別人不能亂動


繼承就像兒子繼承父親的基因和財產,兒子天生就有父親的特征(屬性和方法,但兒子還可以有自己獨特的技能(擴展功能)。在編程里,繼承就是子類自動擁有父類的代碼,可以復用和擴展可以不用重復造輪子


多態就像大家就像大家都能說“打招呼”,但表達方式不同:

  • 中國人說:“你好!”
  • 美國人說:“Hello!”
  • 日本人說:“こんにちは!”
    雖然動作一樣,但不同人表現不同,在編程里,多態就是同一個接口,不同對象有不同的實現可以讓代碼更靈活

C++類與對象初識

  • 類(class):定義了一類事物的屬性和行為,是一種模板/藍圖
  • 對象(object):類的實例,是實際存在的個體

類的定義

類的定義由關鍵字class開始,并通過{}包裹類的內容,類的成員包括:

  • 數據成員:用于存儲類對象的狀態(屬性)
  • 成員函數:描述對象可以執行的行為(操作)
class Car {
private:string model;  // 數據成員int year;      // 數據成員
public:// 成員函數:用來設置車輛的型號void setModel(string m);// 成員函數:用來獲取車輛的型號string getModel();// 成員函數:用來設置車輛的年份void setYear(int y);// 成員函數:用來獲取車輛的年份int getYear();
};

類的對象

類定義之后,我們可以創建該類的對象,類的對象即是類的實例化

int main() {Car myCar;               // 創建一個名為 myCar 的 Car 類型對象myCar.setModel("BMW");    // 設置 myCar 的 modelmyCar.setYear(2021);      // 設置 myCar 的 yearcout << myCar.getModel() << " " << myCar.getYear() << endl;  // 輸出:BMW 2021return 0;
}

類的訪問控制與封裝

想象一下你在銀行開了一個賬戶,賬戶里有余額,你或者其他人都不能跑到銀行的數據庫去修改余額,比如改成999999999999,這樣做明顯是不合理的,銀行只給你兩個合法的窗口:存錢和取錢,這樣設計的好處有:你的余額不會被隨便修改,安全性高,你只需要關心“怎么存取錢”,而不用操心銀行內部如何記賬,銀行后臺可以隨時升級換系統,對客戶來說使用方式不變,這其實就是封裝與訪問控制的真實寫照

為了保護數據安全,簡化使用,方便維護,體現面向對象思想,C++要對類進行訪問控制與封裝。

在C++中,類的成員默認是私有的,也就是說,外部無法直接訪問類的成員變量,如果希望外部能夠訪問成員,必須通過公共接口來提供訪問權限

訪問權限

  • public:公有成員,類外部可以訪問
  • private:私有成員,類外部無法直接訪問
  • protected:保護成員,類外部無法直接訪問,但可以被派生類訪問
class Car {
private:string model;  // 私有成員變量
public:void setModel(string m) { model = m; }  // 公有成員函數string getModel() { return model; }     // 公有成員函數
};

類的成員函數

類成員函數的定義方式

在C++中,類中的成員函數可以通過兩種方式進行定義:

  1. 將類的聲明與實現都放在一個 .h 文件中

  2. 將類的聲明放在 .h 文件中,將實現放在 .cpp 文件中

我們首先來看第一種方式:

將聲明和定義都放在 .h 文件中的方式

這種做法并不推薦,主要有以下幾個問題:

  1. 可能導致重復定義:如果 .h 文件被多個源文件包含,就會在每個源文件中生成一份函數的實現,導致鏈接時發生重復定義錯誤。

  2. 編譯速度變慢:每個源文件都會重新編譯類的實現部分,導致編譯時間增加。

  3. 模塊邊界不清晰:將實現放在頭文件中,會讓代碼的結構變得不清晰,維護起來比較困難。

例如,下面是一個簡單的例子:

#pragma once
#include <iostream>
#include <string>class Person {std::string _name;std::string _sex;int _age;
public:Person(std::string name, std::string sex, int age) {_name = name;_sex = sex;_age = age;}void show();  // 函數聲明
};// 這里是函數定義,直接放在了頭文件中
void Person::show() {std::cout << "姓名:" << _name << std::endl;std::cout << "性別:" << _sex << std::endl;std::cout << "年齡:" << _age << std::endl;
}
#include"Person.h"
int main()
{Person p("張三", "男", 20);p.show();
}

然后在另一個 .cpp 文件中:

#include"Person.h"
void test()
{Person p1("張三", "男", 20);p1.show();
}

上述代碼不能成功編譯,原因是頭文件中的函數定義會在每個包含該頭文件的 .cpp 文件中生成一份,最終會導致鏈接時出現重復定義的錯誤。

重復定義錯誤示意圖

即使沒有發生重復定義,編譯速度也會因為每個源文件都需要重新編譯函數實現部分而變慢。此外,這種做法會導致模塊之間的邊界不清晰,代碼的結構會變得不容易維護。

將類的聲明放在 .h 文件中,將實現放在 .cpp 文件中

將類的聲明放在.h文件中,實現放在.cpp文件中,是C++開發中的標準做法,不僅解決了上面重復定義的問題還帶來了提升編譯效率,增強代碼的模塊化、封裝性可維護性,同時也提高了 代碼的可讀性可重用性 的好處。這種做法是C++中的標準實踐

總結

在本篇博客中,我們對比了面向過程(Procedural Programming)與面向對象(Object-Oriented Programming)兩種常見的編程思想,并通過通俗易懂的示例進行了講解。

  • 面向過程強調程序的執行順序,適用于邏輯簡單、功能明確的小型程序。它通過將問題拆解為一系列步驟或函數,著重于“怎么做”。

  • 面向對象則通過模擬現實世界中的對象與關系,將數據與操作封裝到對象中,強調“誰來做”。它通過封裝、繼承和多態這三大特性,提升了代碼的復用性、擴展性和可維護性,適合大型、復雜的系統設計。

通過代碼示例,我們展示了兩種思想在實際編程中的應用。面向過程的設計直接關注操作步驟,靈活快捷,但擴展性差;而面向對象則通過抽象和封裝將數據與行為結合,便于擴展與維護。不同的場景下,我們可以根據程序的復雜度和需求來選擇合適的設計思想。
在學習和使用面向對象時,我們還討論了類與對象的基本概念、封裝與訪問控制的實現方式,了解了如何設計和組織代碼,使其更具可讀性、可維護性與可擴展性。
最終,面向過程面向對象并不是對立的,二者各有優劣。在實際開發中,我們往往會根據具體需求綜合使用它們,從而達到最佳的開發效果。掌握這兩種編程思想,并在合適的場景中應用,將使我們成為更高效、更有創造力的軟件開發者。

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

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

相關文章

C++ Int128 —— 128位有符號整數類實現剖析

&#x1f9e0; C Int128 —— 128位有符號整數類實現剖析 引用&#xff1a;openppp2/ppp/Int128.h &#x1f3d7;? 1. 存儲結構設計 #mermaid-svg-2JDFsdz6MTbX253D {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-sv…

【C 語言生成指定范圍隨機數(整數 + 小數):原理、實現與避坑指南】

概述 在 C 語言開發中&#xff0c;生成指定范圍的隨機數是高頻需求&#xff08;如游戲隨機道具、數據模擬、測試用例生成等&#xff09;。但很多新手會卡在 “范圍控制”“隨機數重復”“小數生成” 等問題上。本文結合實戰場景&#xff0c;從原理到代碼詳細講解如何生成 1100、…

一個簡單的langgraph agent系統

本文基于langgraph的預制件 Agent Chat UI和《搭建一個本地langgraph服務》中的本地服務構建一個簡單的agent系統。 說明&#xff1a;Agent Chat UI需要nodejs版本18及以上&#xff0c;而nodejs18需要的glibc版本為2.28&#xff0c;本人使用操作系統為ubuntu18.04&#xff0c;g…

通過SSH來推送本地文件夾到Github

配置SSH git使用SSH配置&#xff0c; 初始需要以下三個步驟 使用秘鑰生成工具生成rsa秘鑰和公鑰 將rsa公鑰添加到代碼托管平臺 將rsa秘鑰添加到ssh-agent中&#xff0c;為ssh client指定使用的秘鑰文件 具體操作如下&#xff1a; 第一步&#xff1a;檢查本地主機是否已經存在…

視頻轉webp批量處理工具哪個好?這里有答案

你是不是也遇到過這樣的困擾&#xff1a;手機里存滿了精彩的短視頻&#xff0c;想做成動圖分享到社交媒體&#xff0c;卻發現轉換后的GIF文件巨大無比&#xff0c;畫質還慘不忍睹&#xff1f;要怎么把手機視頻轉webp&#xff0c;才能既保持高清畫質&#xff0c;又能大幅減小文件…

【Fastjson】Fastjson2 在不同 Modules 模塊包下,@JSONField name映射無法反序列化的 BUG 及解決

問題&#xff1a;在使用 alibaba fastjson2 做 JSONField 字段名映射時&#xff0c;在同模塊包下 Flink Jar 任務正常映射&#xff0c;本地測試正常映射&#xff0c;但是將兩個模塊包上傳至 Flink Cluster 之后&#xff0c;出現反序列化異常&#xff0c;子模塊無法反序列化父模…

Go語言基礎---數據類型間的故事

Go語言基礎—數據類型間的故事 目錄 前言基本數據類型 整形字節特殊整形unsafe.Sizeof數字字面量語法浮點型布爾值字符串byte和rune類型 運算符 算術運算符關系運算符邏輯運算符位運算符賦值運算符 前言 Go語言是Google開發的一種靜態強類型、編譯型語言。Go語言語法與C相近…

dedecms軟件等級★號改成圖片圖標顯示的辦法

我們在用到dedecms織夢的軟件模型&#xff0c;在調用軟件星級的時候&#xff0c;要把默認的星號改為圖片&#xff0c;這個要怎么操作呢&#xff1f;1、軟件模型管理里面-字段管理-字段配置softrankislink一行改為&#xff1a;<field:softrank itemname軟件等級 typeint isnu…

windows下安裝claude code+國產大模型glm4.5接入(無需科學上網)

下載安裝node.js https://nodejs.org/en/download 安裝版.msi 直接下載安裝即可 免安裝版.zip 1.解壓下載的壓縮包 2.創建數據緩存存儲目錄cache和全局安裝工具目錄global 3.配置環境變量 【我的電腦】右鍵選中【屬性】-> 找到【高級系統設置】-> 右下角【環境變量…

嵌入式 - ARM4

裸機實現LED閃爍一、啟動代碼1. 異常向量表配置1. .global匯編器指令&#xff0c;全局定義標簽_start&#xff0c;作為匯編程序的默認起點2. 配置標簽配置標簽時可以前置加_ &#xff0c;以便和普通標簽或系統標簽做區分3. 異常向量表ARM架構規定異常向量表位置固定&#xff0c…

《C++ 108好庫》之2 多線程庫thread,mutex,condition_variable,this_thread

《C 108好庫》之之2 多線程庫thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_thread《C 108好庫》之2 多線程庫thread&#xff0c;mutex&#xff0c;condition_variable&#xff0c;this_threadstd::thread類??互斥量&#xff08;Mutex&#xff09;…

Android系統框架知識系列(二十):專題延伸:JVM vs ART/Dalvik - Android運行時演進深度解析

?關鍵詞?&#xff1a;運行時優化、AOT編譯、JIT編譯、內存管理、電池效率、性能分析一、Android運行時演進背景1. 移動環境的特殊挑戰Android運行時環境的演進源于移動設備的獨特限制&#xff1a;?移動設備約束條件?&#xff1a;?有限的內存資源?&#xff1a;早期設備僅1…

ubuntu 22 安裝輕量級桌面Xfce并使用xrdp遠程桌面連接

1.安裝Xfce:sudo apt install xubuntu-desktop -y2.安裝xrdp:sudo apt install xrdp -y3.配置xrdp&#xff0c;nano /etc/xrdp/xrdp.ini:[Globals] ... port3389 ; 遠程連接端口&#xff0c;默認是3389&#xff0c;可以改成自己喜歡的端口... ; ; Session types ;; Some sess…

【Flask】測試平臺開發,數據看板開發-第二十一篇

概述&#xff1a;在前面我們已經實現了我們的產品創建管理&#xff0c;應用管理管理&#xff0c;需求提測管理但是每周提測了多少需求&#xff0c;創建了哪些產品&#xff0c;我們是不是看著不是很直觀&#xff0c;接下來我們就需要開發一個數據看板功能&#xff0c;實現能夠看…

我是程序員,不是程序猿:請別把我當猴耍——拒絕被低估,用專業贏得尊重

摘要 本文旨在深度剖析“程序員”與“程序猿”一字之差背后所反映的職業尊嚴與身份認同問題。我們生活在一個技術驅動的時代&#xff0c;但對技術創造者的認知卻常常被“程序猿”、“碼農”等標簽簡單化、甚至矮化。本文將從正名開始&#xff0c;辨析“程序員”的專業內涵&…

C++中vector刪除操作的安全隱患與最佳實踐

std::vector 是C標準模板庫&#xff08;STL&#xff09;中最常用的動態數組容器&#xff0c;提供了高效的隨機訪問和動態擴容能力。然而&#xff0c;其刪除操作如果使用不當&#xff0c;會引入嚴重的安全隱患&#xff0c;包括未定義行為、內存泄漏和數據競爭等問題。本文將深入…

Unix/Linux 系統中的 `writev` 系統調用

<摘要> 本文對 Unix/Linux 系統中的 writev 系統調用進行了全面深入的解析。內容涵蓋了其產生的背景&#xff08;從傳統 write 的局限性到分散/聚集 I/O 概念的引入&#xff09;、核心概念&#xff08;如 struct iovec、系統調用流程&#xff09;。重點剖析了其設計意圖&…

深入理解 Android targetSdkVersion:從 Google Play 政策到依賴沖突

深入理解 Android targetSdkVersion&#xff1a;從 Google Play 政策到依賴沖突 作為 Android 開發者&#xff0c;你很可能在 Android Studio 中見過這條提示&#xff1a;Google Play requires that apps target API level 33 or higher。它像一個盡職的提醒者&#xff0c;時常…

灰匣(GrayBox)1.0.0 發布【提升系統權限APP】

灰匣是一個提升系統權限的工具&#xff0c;可以配合Root、三方軟件&#xff08;Shizuku&#xff09;以及【設備管理員】&#xff08;設備所有者&#xff09;實現一些高級功能及底層接口&#xff0c;可以自動隔離&#xff08;凍結/禁用&#xff09;不必要的應用&#xff0c;如某…

PAT 1104 Sum of Number Segments

這一題的大意就是找一個數組中的所有子數組&#xff0c;它們的累加和為多少&#xff0c; 題目上給出的數據范圍是O(n^5)那么只能遍歷一次&#xff0c;不能用暴力的方法求出。 看到這一題我有兩個思路&#xff1a; 1.試圖用雙指針和滑動窗口來把O&#xff08;n^2)的時間復雜度降…