日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C++之类和对象

發布時間:2023/12/18 c/c++ 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C++之类和对象 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一,C中結構體的缺陷

1,main函數中的任意賦值語句都可以訪問結構體中的成員,但在現實生活中并不是什么數據都可以被隨意訪問的,因此C語言中的結構體的數據是不安全的;

2,結構體中的數據和對該數據的操作是分離的,并不是一個被封裝起來的整體,因此使程序難以重用,影響了軟件生產效率;于是C++中引入了類的概念。

?客戶/服務模型

? OOP(面向對象程序設計)程序員常依照客戶/服務模型來討論程序設計。在這個概念中,客戶是使用類的程序。類聲明(包括類方法)構成了服務器,他是程序可以使用的資源。客戶只能通過以公有方式定義的接口使用服務器,這意味著客戶程序員唯一的責任是了解該接口。服務器設計人員的責任時確保服務器根據該接口可靠并準確的執行。服務器設計人員只能修改類設計的實現細節,而不能修改接口。這樣程序員獨立的對接口和服務器進行改進,對服務器的修改不會對客戶的行為造成意外的影響。

?

二,類與對象

#include <iostream> using namespace std;class Point {private:static int count; //記錄構造的對象數,靜態數據成員int x_;int y_;string name_;public:Point(const string &name, int i, int j); //帶參構造函數Point(); //默認構造函數,構造函數重載Point(const Point &p); //拷貝構造函數~Point(void); //析構函數static void showCount(); //靜態成員函數void showPoint();int ReadX() const{//內聯成員函數(隱式聲明),在聲明前面加inline修飾顯示聲明內聯函數return x_;}; int ReadY() const {return y_; }; };//成員函數實現部分 Point::Point(const string & name, int x, int y) {count++;name_ = name;x_ = x;y_ = y;cout<<count<<":調用非默認構造函數:Point("<<name_<<","<<x_<<","<<y_<<")"<<endl; }Point::Point() {count++;x_ = y_ = 0; name_ = "no name";cout<<count<<":調用默認構造函數:Point("<<name_<<","<<x_<<","<<y_<<")"<<endl; }Point::Point(const Point &p) {count++;name_ = p.name_;x_ = p.x_;y_ = p.y_;cout<<count<<":調用拷貝構造函數:Point("<<name_<<","<<x_<<","<<y_<<")"<<endl; }void Point::showPoint() {cout<<"Point對象:"<<name_<<","<<x_<<","<<y_<<endl; }void Point::showCount() {cout<<"目前已經創建了count="<<count<<"個對象"<<endl; }Point::~Point(void) {count--;cout<<"調用析構函數,釋放類Point("<<name_<<","<<x_<<","<<y_<<")"<<endl; }int Point::count = 0; //初始化靜態數據成員,注意使用類名限定 Point func(Point pointA);int main(void) {{Point pointA("pointA", 20, 30);Point pointC(pointA); //用pointA初始化pointC,調用拷貝構造函數(1) pointC.showPoint();Point pointB; //pointB的數據成員被初始化為0//賦值運算,這里不是初始化.創建一個臨時對象然后賦值給pointBpointB = Point("pointB", 1, 2); Point pointD = Point("pointD", 3, 4); //使用臨時對象初始化pointD//Point pointE{"pointE", 5, 6};//使用初始化列表初始化pointE, C++11 Point *pointP = new Point("pointP", 7, 8); //C++11delete pointP;pointB = func(pointA);pointB.showPoint();cout<<"Done!"<<endl;}cout<<"exit now!\n";return 0; }Point func(Point pointA) //類作形參,調用拷貝構造函數(2) {cout<<"在func函數體內\n";return Point("temp", pointA.ReadX()+10, pointA.ReadY()+10); //定義臨時對象,調用拷貝構造函數3次返回Point類 } View Code

運行結果(VC6.0):

1:調用非默認構造函數:Point(pointA,20,30)
2:調用拷貝構造函數:Point(pointA,20,30)
Point對象:pointA,20,30
3:調用默認構造函數:Point(no name,0,0)
4:調用非默認構造函數:Point(pointB,1,2)
調用析構函數,釋放類Point(pointB,1,2)
4:調用非默認構造函數:Point(pointD,3,4)
5:調用非默認構造函數:Point(pointP,7,8)
調用析構函數,釋放類Point(pointP,7,8)
5:調用拷貝構造函數:Point(pointA,20,30)
在func函數體內
6:調用非默認構造函數:Point(temp,30,40)
調用析構函數,釋放類Point(temp,30,40)
調用析構函數,釋放類Point(pointA,20,30)
Point對象:temp,30,40
Done!
調用析構函數,釋放類Point(pointD,3,4)
調用析構函數,釋放類Point(temp,30,40)
調用析構函數,釋放類Point(pointA,20,30)
調用析構函數,釋放類Point(pointA,20,30)
exit now!

1,類與對象

  數據成員:只有數據類型,無存儲類型,因此不能再類的聲明中初始化數據成員;在類外,不能訪問私有和保護成員

  成員函數在類外定義:

    返回值類型 ? [類名::]成員函數名(參數表) ?{ 函數體 }

成員函數體內可以訪問該類的所有數據成員;非靜態成員函數中都有一個隱含的參數,即this指針,該指針指向當前正在調用成員函數的對象

2,構造函數與析構函數

默認構造函數:當且僅當沒有定義任何構造函數時,編譯器才會提供默認構造函數。所以當定義非默認的構造函數時,必須定義默認構造函數,否則下面的聲明將會出錯:

?????????????????????? Point pointB; //調用默認構造函數

? 或者是給非默認構造函數提供默認值:Point(const string &name = "no name", int x=0, int y=0);

析構函數:無參數不可重載,在對象存在的函數體結束時或使用delete釋放new創建的對象時被自動調用

缺省拷貝構造函數:把初始對象的每個數據成員的值都復制到新建對象中

它們都沒有返回值;調用析構函數和構造函數的順序正好相反;對沒有定義構造函數的類,其公有數據成員可以用初始化值表進行初始化

拷貝構造函數的調用

a,由一個類的對象M初始化該類另一個對象N時:Point N(M);

b,當類的對象N作為函數實參傳遞給函數形參時:P = func(N);

3,類的作用域

定義成員函數時,使用作用域運算符(::)來標識所屬的類。

類的作用域:類作用域意味著不能不能從外部直接訪問類的成員,公有成員函數也是如此。在類聲明或成員函數定義中,可以使用未限定的成員名稱 。在其他情況下使用類成員名時,必須根據上下文使用直接成員運算符(.),間接成員運算符(->)或作用域解析運算符(::)。

作用域為類的常量

class Bakery { private:static const int Months = 12; //該常量與其他靜態變量存儲在一起,而不是存儲在對象中double costs[Months]; };//或者定義枚舉常量 class Bakery { private:enum {Months = 12};double costs[Months]; };

?

作用域內枚舉

當兩個枚舉定義中的枚舉量可能發生沖突時,可以定義作用域為類的枚舉。如下所示:

//發生沖突的枚舉定義 enum egg {Small, Medium, Large, Jumbo}; enum t_shirt {Small, Medium, Large, Xlarge};//類作用域的枚舉定義 enum calss egg {Small, Medium, Large, Jumbo}; enum class t_shirt {Small, Medium, Large, Xlarge};enum egg choice = egg::Large; enum t_shirt Floyd = t_shirt::Large;

C++11還提供了作用域內枚舉的類型安全。在有些情況下,常量枚舉將自動轉換為整形,但作用域內枚舉不能隱式的轉換為整形。

但在必要時可以進行顯示類型轉換:int Floyd = int(t_shirt::Large);

?

?

3,注意事項

a,定義類的指針時,不調用類的構造函數;拷貝構造函數也是構造函數的重載

b,malloc/free和new/delete(C++)

調用malloc和free沒有調用構造和析構函數,而調用new和delete給類指針分配存儲空間可以執行構造和析構函數,也可以為其他類型的指針分配存儲空間。必須配對使用。

c,"類名 對象名",當定義了構造函數,調用的是無參的構造函數創建對象或者是帶默認形參的構造函數,沒有定義構造函數時,調用的是缺省構造函數。而"類名 對象名()" 不能調用任何一種構造函數。

d,使用inline定義的內聯函數必須將類的聲明和內聯成員函數的定義都放在同一個文件中,否則編譯時無法進行代碼的置換

e,this指針的作用:C++的編譯系統用一段空間來存放各個對象共同的函數代碼段,每個對象的存儲空間只是對象數據成員所占用的存儲空間。而成員函數就是通過this指針知道是哪個對象調用了

?

三,共享機制一(靜態成員)

靜態成員實現一個類多個對象之間的數據共享

1,靜態數據成員

是類的所有對象共享的成員,靜態數據成員的值對每一個對象是一樣的,可以被該類的任何一個對象更新。靜態數據成員在聲明類的時候就分配了內存,在定義對象之前就存在了。

必須在類外初始化:?

    <數據類型> <類名>::<靜態數據成員名> = <值>?//一般放在類定義之后

類外對公有靜態數據成員的引用:?

   ??<類名>::<公有靜態成員名> 或 <對象名>.<公有靜態成員名>

2,靜態成員函數

能直接引用類中的靜態成員,但只能通過對象,對象的指針或引用來訪問類中的非靜態成員(類的對象做函數參數);靜態成員函數中沒有this指針

使用格式:?

    <類名>::<公有靜態成員函數名>(<參數表>) 或 <對象名>.<公有靜態成員函數名>(<參數表>)

?

四,類的組合

指一個類內嵌其他類的的對象作為成員的情況,兩個類間是包含與被包含的關系

創建對象時,內嵌的對象成員會被自動創建,因此要初始化本類的基本數據成員和內嵌的對象成員

組合類構造函數(需通過初始化列表對內嵌對象初始化): ? ? ?

    類名::類名(形參表):內嵌對象1(形參表1),內嵌對象2(形參表2),…… {類的初始化}

#include <iostream> using namespace std; #include <cmath> class Point { private:int x,y; public:Point(int i, int j):x(i),y(j) { cout<<"調用Point構造函數:Point("<<x<<", "<<y<<")"<<endl; }Point(const Point &p) { cout<<"調用Point拷貝構造函數"<<endl; x=p.x; y=p.y; }int ReadX() { return x; }int ReadY() { return y; }~Point() { cout<<"調用Point析構函數"<<endl; } };class Line { public:Line(Point xp1, Point xp2); Line(int i, int j, int m, int n); //構造函數重載~Line() { cout<<"調用Line析構函數"<<endl; } private:Point p1, p2; };Line::Line(Point xp1, Point xp2):p1(xp1),p2(xp2) {cout<<"調用Line構造函數1: ";cout<<"Point("<<p1.ReadX()<<", "<<p1.ReadY()<<") Point("<<p2.ReadX()<<", "<<p2.ReadY()<<")"<<endl; }Line::Line(int i, int j, int m, int n):p1(i,j),p2(m,n) {cout<<"調用Line構造函數2: ";cout<<"Point("<<p1.ReadX()<<", "<<p1.ReadY()<<") Point("<<p2.ReadX()<<", "<<p2.ReadY()<<")"<<endl; }void main() {Line line1(Point(1,2), Point(3,4)); //用臨時對象做實參Line line2(5,6,7,8); } View Code

運行結果(VC++6.0):

注意事項:

<1>自身類的對象不可以作為該類的成員;自身類的引用或指針可以作為該類的成員(遞歸類)

<2>前向引用聲明

class N; class M {private: N *n;}; //n是N類的指針 class N {public: void f(M m);}; //m是M類的對象

?

五,共享機制二(友元函數和友元類)

友元提供了不同類或對象的成員函數之間、類的成員與一般函數之間進行數據共享的機制。

<1>友元函數

在友元函數體中可以通過對象名訪問類的私有和保護成員。友元函數分友元非成員函數和友元成員函數。

友元非成員函數

友元函數為非成員函數,那么在定義該函數時不用在前面加"類名::",同樣的它也沒有所謂的this指針

#include <iostream> using namespace std;class Employee { private:char *name;char *id;static int count; public:Employee(char* name, char* id);~Employee();static void showEmployeeCount();friend void showEmployee(Employee &emp); };Employee::Employee(char* name, char* id) {this->count ++;this->name = new char[strlen(name)+1];this->id = new char[strlen(id)+1];strcpy(this->name, name);strcpy(this->id, id); }void Employee::showEmployeeCount() { cout<<"雇員總數: count="<<count<<endl; }void showEmployee(Employee &emp) //友元非成員函數定義 {cout<<"name="<<emp.name<<", id="<<emp.id<<endl; }Employee::~Employee() {delete []name;delete []id; }int Employee::count = 0;void main() {Employee emp[3] = { //創建臨時對象初始化對象數組Employee("haha", "11070000"),Employee("hehe", "11070001"),Employee("yiyi", "11070002")};for (int i=0; i<3; i++){showEmployee(emp[i]); //友元非成員函數的調用 }emp->showEmployeeCount(); } View Code

運行結果(VC6.0):

友元成員函數

友元成員函數不僅可以訪問自己所在類對象中的私有,公有或保護成員,也可以訪問friend聲明語句所在的類對象中的所有成員,這樣就實現了類與類之前的協作

#include <iostream> using namespace std; #include <string>class Salary; //前向引用聲明class Employee { private:string name;string id;static int count; public:Employee(string name, string id);static void showEmployeeCount();void showEmployee(Salary &sal); //成員函數,參數是Salary對象的引用 };Employee::Employee(string name, string id):name(name),id(id) {this->count ++; }void Employee::showEmployeeCount() { cout<<"雇員總數: count="<<count<<endl; }int Employee::count = 0;class Salary { private:double salary; //薪水double wage; //工資double bonus; //獎金double commission; //提成 public:Salary(double salary, double wage, double bonus, double commission);friend void Employee::showEmployee(Salary &sal); };Salary::Salary(double salary, double wage, double bonus, double commission):salary(salary),wage(wage),bonus(bonus),commission(commission) {}void Employee::showEmployee(Salary &sal) //友元非成員函數定義 {cout<<"name="<<name<<", id="<<id<<endl;cout<<"salary: "<<sal.salary<<endl; //可以訪問Salary類中的私有數據成員cout<<"wage: "<<sal.wage<<endl;cout<<"bonus: "<<sal.bonus<<endl;cout<<"commission: "<<sal.commission<<endl; }void main() {Employee emp("yiyi", "11070002");Salary sal(10000,50000,30000,20000);emp.showEmployee(sal);emp.showEmployeeCount(); } View Code

運行結果:

注意,在涉及到這種類的前向引用聲明的,將成員函數Employee::showEmployee(Salary &sal)的實現放在這兩個類的定義之后.要不然編譯時會出錯

<2>友元類

如果一個類被說明為另一個類的友元類,那么這個類的所有成員函數都將成為另一個類的友元函數。

注意:友元關系是單向的,不具有交換性,也不具有傳遞性。比如類A為類B的友元類,類B為類C的友元類,并不代表類A為類C的友元類,是不是友元類,看其類A有沒有在類C中聲明;

?

六,C++的多文件程序

C++的源程序基本上由3個部分組成:類的聲明部分、類的實現部分和類的使用部分,針對3個部分,C++中對應分為3個文件:類聲明文件(*.h文件)、類的實現文件(*.cpp)和類的使用文件(*.cpp,主函數main文件)。

分為3部分主要有以下幾個方面:(1)類的實現文件通常會比較大,將類的聲明和實現放在一起,不利于程序的閱讀、管理和維護。我們通常說接口應該和實現的部分分離,這樣可以更易于修改程序。(2)把類成員函數的實現放在聲明文件中和單獨放實現文件里,在編譯時是不一樣的。前者是作為類的內聯函數來處理的。(3)對于軟件的廠商來說,它只需向用戶提供程序公開的接口(只需提供*.h文件),而不用公開程序源代碼。
?

轉載于:https://www.cnblogs.com/zhoutian220/p/4032050.html

總結

以上是生活随笔為你收集整理的C++之类和对象的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。