C++中級基礎(chǔ)(上)

C++類 & 對象

C++在C語言的基礎(chǔ)上增加面向?qū)ο缶幊?,也就是說C++支持面向?qū)ο蟪绦蛟O(shè)計(Java python都是支持面向?qū)ο蟪绦蛟O(shè)計的)。類是C++的核心特性,通常被稱為用戶定義的類型。
類定義以關(guān)鍵字class開頭,后跟類的名稱。類的主體是包含在一對花括號中,類定義后必須跟著一個分號或一個聲明列表。關(guān)鍵字public確定類成員的訪問屬性,在類對象作用域內(nèi),公共成員在類的外面是可以訪問的。對象是根據(jù)類來創(chuàng)建的,聲明類的對象就像聲明基本類型的變量一樣。

class Box
{
   public:
      double length;   // 盒子的長度
      double breadth;  // 盒子的寬度
      double height;   // 盒子的高度
};
Box Box1;          // 聲明 Box1,類型為 Box

舉例:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;   // 長度
      double breadth;  // 寬度
      double height;   // 高度
};
 
int main( )
{
   Box Box1;        // 聲明 Box1,類型為 Box
   Box Box2;        // 聲明 Box2,類型為 Box
   double volume = 0.0;     // 用于存儲體積
 
   // box 1 詳述
   Box1.height = 5.0; 
   Box1.length = 6.0; 
   Box1.breadth = 7.0;
 
   // box 2 詳述
   Box2.height = 10.0;
   Box2.length = 12.0;
   Box2.breadth = 13.0;
 
   // box 1 的體積
   volume = Box1.height * Box1.length * Box1.breadth;
   cout << "Box1 的體積:" << volume <<endl;
 
   // box 2 的體積
   volume = Box2.height * Box2.length * Box2.breadth;
   cout << "Box2 的體積:" << volume <<endl;
   return 0;
}

C++類成員函數(shù)
類的成員函數(shù)是指那些把定義和原型寫在類定義內(nèi)部的函數(shù),就像類定義中的其他變量一樣。類成員函數(shù)是類的一個成員,它可以操作類的任意對象,可以訪問對象中的所有成員。
使用成員函數(shù)來訪問類的成員,而不是直接訪問這些類的成員:

class Box
{
   public:
      double length;         // 長度
      double breadth;        // 寬度
      double height;         // 高度
      double getVolume(void);// 返回體積
};

定義在類中的成員函數(shù)缺省都是內(nèi)聯(lián)的,如果在類中未給出成員函數(shù)定義,而又想內(nèi)聯(lián)該函數(shù)的話,那在類外要加上inline并使用范圍解析運(yùn)算符::定義該函數(shù),否則就認(rèn)為不是內(nèi)聯(lián)的。需要強(qiáng)調(diào)的是在::運(yùn)算符之前必須使用類名。

// 頭文件
class A
{
    public:
    void Foo(int x, int y);
}
// 定義文件
inline void A::Foo(int x, int y){}

調(diào)用成員函數(shù)是在對象上使用點(diǎn)運(yùn)算符(.)

Box myBox;          // 創(chuàng)建一個對象
 
myBox.getVolume();  // 調(diào)用該對象的成員函數(shù)

C++類訪問修飾符
關(guān)鍵字public,private,protected稱為訪問修飾符
public 公有成員在程序中類的外部是可訪問的,在不使用任何成員函數(shù)來設(shè)置和獲取公有變量的值。
private 私有成員變量或函數(shù)在類的外部是不可訪問的,甚至是不可查看的。只有類和友元函數(shù)可以訪問私有成員。在沒有使用任何訪問修飾符時,類的成員將被假定為私有成員
protected 保護(hù)成員在派生類(即子類)中是可訪問的。
繼承中public,protected,private的繼承方式:

image.png

C++ 類構(gòu)造函數(shù) & 析構(gòu)函數(shù)
類的構(gòu)造函數(shù)是類的一種特殊的成員函數(shù),它會在每次創(chuàng)建類的新對象時執(zhí)行。構(gòu)造函數(shù)的名稱與類的名稱是完全相同的,并不會返回任何類型,也不會返回void,可用于為某些成員變量設(shè)置初始值。

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 這是構(gòu)造函數(shù)
 
   private:
      double length;
};
 
// 成員函數(shù)定義,包括構(gòu)造函數(shù)
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函數(shù)
int main( )
{
   Line line; //類的新對象line,此時執(zhí)行構(gòu)造函數(shù)
 
   // 設(shè)置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

輸出

Object is being created
Length of line : 6

同理,帶參數(shù)的構(gòu)造函數(shù)在創(chuàng)建對象時會給對象賦初始值。

使用初始化列表來初始化字段
Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}
等價于
Line::Line( double len)
{
    length = len;
    cout << "Object is being created, length = " << len << endl;
}
類的析構(gòu)函數(shù)

類的析構(gòu)函數(shù)是類的一種特殊的成員函數(shù),會每次刪除所創(chuàng)建的對象時執(zhí)行。析構(gòu)函數(shù)的名稱與類的名稱是完全相同的,只是在前面加波浪號(~)作為前綴,也不能帶有任何參數(shù)。析構(gòu)函數(shù)有助于在跳出程序(比如關(guān)閉文件,釋放內(nèi)存等)前釋放資源。

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();   // 這是構(gòu)造函數(shù)聲明
      ~Line();  // 這是析構(gòu)函數(shù)聲明
 
   private:
      double length;
};
 
// 成員函數(shù)定義,包括構(gòu)造函數(shù)
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
Line::~Line(void)
{
    cout << "Object is being deleted" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函數(shù)
int main( )
{
   Line line;
 
   // 設(shè)置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 //析構(gòu)函數(shù)在釋放內(nèi)存前釋放資源
   return 0;
}

輸出

Object is being created
Length of line : 6
Object is being deleted

強(qiáng)調(diào)一點(diǎn) C++初始化類成員時,是按照聲明的順序初始化的,而不是按照出現(xiàn)在初始化列表中的順序。
拷貝構(gòu)造函數(shù)
拷貝構(gòu)造函數(shù)是一種特殊的構(gòu)造函數(shù),它在創(chuàng)建對象時是使用同一類中之前創(chuàng)建的對象來初始化新創(chuàng)建的對象??截悩?gòu)造函數(shù)通常用于:
1,通過使用另一個同類型的對象來初始化新創(chuàng)建的對象
2,復(fù)制對象把它作為參數(shù)傳遞給函數(shù)
3,復(fù)制對象,并從函數(shù)返回這個對象

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      int getLength( void );
      Line( int len );             // 簡單的構(gòu)造函數(shù)
      Line( const Line &obj);      // 拷貝構(gòu)造函數(shù)
      ~Line();                     // 析構(gòu)函數(shù)
 
   private:
      int *ptr;
};
 
// 成員函數(shù)定義,包括構(gòu)造函數(shù)
Line::Line(int len)
{
    cout << "調(diào)用構(gòu)造函數(shù)" << endl;
    // 為指針分配內(nèi)存
    ptr = new int;
    *ptr = len;
}
 //拷貝構(gòu)造函數(shù) obj是一個對象引用,該對象用于初始化另一個對象
Line::Line(const Line &obj)
{
    cout << "調(diào)用拷貝構(gòu)造函數(shù)并為指針 ptr 分配內(nèi)存" << endl;
    ptr = new int;
    *ptr = *obj.ptr; // 拷貝值
}
 
Line::~Line(void)
{
    cout << "釋放內(nèi)存" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}
 
void display(Line obj)
{
   cout << "line 大小 : " << obj.getLength() <<endl;
}
 
// 程序的主函數(shù)
int main( )
{
   Line line(10);
 
   display(line);
 
   return 0;
}

輸出:

調(diào)用構(gòu)造函數(shù)
調(diào)用拷貝構(gòu)造函數(shù)并為指針 ptr 分配內(nèi)存
line 大小 : 10
釋放內(nèi)存
釋放內(nèi)存

C++友元函數(shù)
類的友元函數(shù)是定義在類外部,但有權(quán)訪問類的所有私有(private)成員和保護(hù)(protected)成員,若友元是一個函數(shù),則該函數(shù)被稱為友元函數(shù);若友元是一個類,該類被稱為友元類這時,整個類及其所有成員都是友元。
如果要聲明函數(shù)為一個類的友元,需要在類定義中該函數(shù)原型前使用關(guān)鍵字friend

class Box
{
   double width;
public:
   double length;
   friend void printWidth( Box box );
   void setWidth( double wid );
};

聲明類ClassTwo的所有成員函數(shù)作為類ClassOne的友元,需要在類ClassOne的定義中放置如下聲明:

friend class ClassTwo;

C++ this 指針
在C++中,每一個對象都能通過this指針來訪問自己的地址,this指針是所有成員函數(shù)的隱含參數(shù)。因此,在成員函數(shù)內(nèi)部,它可以用來指向調(diào)用對象。友元函數(shù)沒有this指針,因?yàn)橛言皇穷惖某蓡T,只有成員函數(shù)才有this指針
C++類的靜態(tài)成員
使用static關(guān)鍵字來把類成員定義為靜態(tài)的,當(dāng)我們聲明類的成員是靜態(tài)時,意味著無論創(chuàng)建多少個類的對象,靜態(tài)成員都只有一個副本。靜態(tài)成員在類的所有對象中是共享的,靜態(tài)成員的初始化是在類的外部通過使用范圍解析運(yùn)算符::來重新聲明靜態(tài)變量從而對它進(jìn)行初始化。靜態(tài)成員函數(shù)的用法是一樣的。

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      static int objectCount;
      // 構(gòu)造函數(shù)定義
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次創(chuàng)建對象時增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // 長度
      double breadth;    // 寬度
      double height;     // 高度
};
 
// 初始化類 Box 的靜態(tài)成員
int Box::objectCount = 0;
 
int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // 聲明 box1
   Box Box2(8.5, 6.0, 2.0);    // 聲明 box2
 
   // 輸出對象的總數(shù)
   cout << "Total objects: " << Box::objectCount << endl;
 
   return 0;
}

C++繼承

繼承允許依據(jù)另一個類來定義一個類,這使得創(chuàng)建和維護(hù)一個應(yīng)用程序變得更容易,也達(dá)到重用代碼功能和提高執(zhí)行時間的效果。當(dāng)創(chuàng)建一個類時不需要重新編寫新的數(shù)據(jù)成員和成員函數(shù),只需指定新建的類繼承已有的類成員即可。這個已有的類稱為基類,新建的類稱為派生類

class derived-class: access-specifier base-class

訪問修飾符 access-specifier是public protected或private其中的一個,base-class是之前定義過的某個類的名稱。如果未使用訪問修飾符access-specifier,則默認(rèn)為private
一個派生類繼承了所有基類方法,但下列情況除外:
基類的構(gòu)造函數(shù),析構(gòu)函數(shù)和拷貝構(gòu)造函數(shù)
基類的重載運(yùn)算符
基類的友元函數(shù)

C++ 重載運(yùn)算符和重載函數(shù)

C++允許在同一個作用域中的某個函數(shù)和運(yùn)算符指定多個定義,分別稱為函數(shù)重載和運(yùn)算符重載
C++中的函數(shù)重載 在同一個作用域中,可以聲明幾個功能類似的同名函數(shù),但是這些同名函數(shù)的形式參數(shù)(指參數(shù)的個數(shù),類型或順序)必須不同。
C++中的運(yùn)算符重載其中重載運(yùn)算符是帶有特殊名稱的函數(shù),函數(shù)名由關(guān)鍵字operator和其后要重載的運(yùn)算符符號構(gòu)成(這部分不太容易理解,小白我就了解了解就好)

Box operator+(const Box&);

C++多態(tài)

多態(tài)意味著調(diào)用成員函數(shù)時,會根據(jù)調(diào)用函數(shù)的對象的類型來執(zhí)行不同的函數(shù)。虛函數(shù)在基類中使用關(guān)鍵字virtual聲明的函數(shù),在派生類中重新定義基類中的虛函數(shù),會告訴編譯器不要靜態(tài)鏈接到該函數(shù)。我們想要的是在程序中任意點(diǎn)可以根據(jù)所調(diào)用的對象類型來選擇調(diào)用的函數(shù),這種操作被稱為動態(tài)鏈接或后期綁定
虛函數(shù)可以不實(shí)現(xiàn)(定義),不實(shí)現(xiàn)(定義)的虛函數(shù)是純虛函數(shù),其聲明如下:

virtual void funtion1()=0;

C++通過創(chuàng)建類來支持封裝和數(shù)據(jù)隱藏,
數(shù)據(jù)封裝是一種數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)捆綁在一起的機(jī)制
數(shù)據(jù)抽象是一種僅向用戶暴露接口而把具體的實(shí)現(xiàn)細(xì)節(jié)隱藏起來的機(jī)制
抽象類(ABC)不能被用于實(shí)例化對象,只能作為接口使用。因此如果一個抽象類的子類需要被實(shí)例化則必須實(shí)現(xiàn)每個虛函數(shù)也就意味著C++支持使用ABC聲明接口。如果沒有在派生類中重寫純虛函數(shù)就嘗試實(shí)例化該類的對象,會導(dǎo)致編譯錯誤。

#include <iostream>
 
using namespace std;
 
// 基類
class Shape 
{
public:
   // 提供接口框架的純虛函數(shù)
   virtual int getArea() = 0;
   void setWidth(int w)
   {
      width = w;
   }
   void setHeight(int h)
   {
      height = h;
   }
protected:
   int width;
   int height;
};
 
// 派生類
class Rectangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height); 
   }
};
class Triangle: public Shape
{
public:
   int getArea()
   { 
      return (width * height)/2; 
   }
};
 
int main(void)
{
   Rectangle Rect;
   Triangle  Tri;
 
   Rect.setWidth(5);
   Rect.setHeight(7);
   // 輸出對象的面積
   cout << "Total Rectangle area: " << Rect.getArea() << endl;
 
   Tri.setWidth(5);
   Tri.setHeight(7);
   // 輸出對象的面積
   cout << "Total Triangle area: " << Tri.getArea() << endl; 
 
   return 0;
}
//輸出
Total Rectangle area: 35
Total Triangle area: 17

感言以前只學(xué)基礎(chǔ)的時候,感覺不到這個深度。發(fā)現(xiàn)有些地方還是不是太理解,可能是還沒練手的緣故吧

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容