我不會C++酌壕,沒問題掏愁,跟凱哥一起學(五)

前言

經(jīng)過四篇散文歇由,終于接觸到了指針相關(guān)知識點我不會C++,沒問題果港,跟凱哥一起學(四)接下來我們繼續(xù):

訪問結(jié)構(gòu)體成員

訪問一個結(jié)構(gòu)體的任何成員沦泌,我們使用 member access operator(成員訪問操作符):(.) 來訪問結(jié)構(gòu)體成 員。成員訪問操作符編碼為結(jié)構(gòu)變量名和我們要訪問結(jié)構(gòu)成員之間的一個點符號辛掠。使用關(guān)鍵字 struct 來定義結(jié) 構(gòu)類型的變量谢谦。

#include <iostream>
#include <cstring>
using namespace std;
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
int main( ) {
   struct Books Book1;// Declare Book1 of type Book
   struct Books Book2;// Declare Book2 of type Book
   // book 1 specification
   strcpy( Book1.title, "Learn C++ Programming");
   strcpy( Book1.author, "Chand Miyan");
   strcpy( Book1.subject, "C++ Programming");
   Book1.book_id = 6495407;
   // book 2 specification
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Yakit Singha");
   strcpy( Book2.subject, "Telecom");
   Book2.book_id = 6495700;
   // Print Book1 info
   cout << "Book 1 title : " << Book1.title <<endl;
   cout << "Book 1 author : " << Book1.author <<endl;
   cout << "Book 1 subject : " << Book1.subject <<endl;
   cout << "Book 1 id : " << Book1.book_id <<endl;
// Print Book2 info
cout << "Book 2 title : " << Book2.title <<endl;
   cout << "Book 2 author : " << Book2.author <<endl;
   cout << "Book 2 subject : " << Book2.subject <<endl;
   cout << "Book 2 id : " << Book2.book_id <<endl;
return 0; }
編譯和執(zhí)行上面的代碼,執(zhí)行結(jié)果如下:
Book 1 title : Learn C++ Programming
Book 1 author : Chand Miyan
Book 1 subject : C++ Programming
Book 1 id : 6495407
Book 2 title : Telecom Billing
Book 2 author : Yakit Singha
Book 2 subject : Telecom
Book 2 id : 6495700

結(jié)構(gòu)體指針

您可以定義結(jié)構(gòu)體指針萝衩,以一種定義指向其他變量的指針非常相似的方式

struct Books *struct_pointer;

現(xiàn)在回挽,您可以用上面定義的指針變量存儲一個結(jié)構(gòu)變量的地址。找到一個結(jié)構(gòu)變量的地址猩谊,把操作符 & 置于結(jié)構(gòu) 體名稱的前面千劈,如下所示:

struct_pointer = &Book1;

為了通過一個指向結(jié)構(gòu)的指針訪問結(jié)構(gòu)體成員,必須使用 -> 操作符牌捷,如下所示:

struct_pointer->title;

讓我們使用結(jié)構(gòu)指針重寫上面的例子墙牌,希望這將幫助你更容易理解這個概念:

#include <iostream>
#include <cstring>
using namespace std;
void printBook( struct Books *book );
struct Books
{
   char  title[50];
   char  author[50];
   char  subject[100];
   int   book_id;
};
int main( ) {
   struct Books Book1;// Declare Book1 of type Book
   struct Books Book2;// Declare Book2 of type Book
   // Book 1 specification
   strcpy( Book1.title, "Learn C++ Programming");
   strcpy( Book1.author, "Chand Miyan");
   strcpy( Book1.subject, "C++ Programming");
   Book1.book_id = 6495407;
   // Book 2 specification
   strcpy( Book2.title, "Telecom Billing");
   strcpy( Book2.author, "Yakit Singha");
   strcpy( Book2.subject, "Telecom");
   Book2.book_id = 6495700;
   // Print Book1 info, passing address of structure
   printBook( &Book1 );
// Print Book1 info, passing address of structure
   printBook( &Book2 );
return 0; }
// This function accept pointer to structure as parameter.
void printBook( struct Books *book )
{
   cout << "Book title : " << book->title <<endl;
   cout << "Book author : " << book->author <<endl;
   cout << "Book subject : " << book->subject <<endl;
   cout << "Book id : " << book->book_id <<endl;
}
編譯和執(zhí)行上面的代碼,執(zhí)行結(jié)果如下:
Book title : Learn C++ Programming
Book author : Chand Miyan
Book subject : C++ Programming
Book id : 6495407
Book title : Telecom Billing
Book author : Yakit Singha
Book subject : Telecom
Book id : 6495700

struct和typedef struct的區(qū)別

在C語言中暗甥,結(jié)構(gòu)體的定義要用typedef struct喜滨,例如:

typedef struct Number{
    int a;
    int b;
}Num;

這里的Number和Num指的都是整個結(jié)構(gòu)體,在聲明結(jié)構(gòu)體變量的時候可以是

struct Number num1;  //聲明結(jié)構(gòu)體變量的第一種方式

也可以是

Num num1;           //聲明結(jié)構(gòu)體變量的第二種方式

也就是說Num==struct Number撤防。定義中的Number其實也可以省略虽风,這樣的話聲明變量就只能是第二種方式了:

typedef struct{     //去掉Number也對
    int a;
    int b;
}Num;
Num num1;   

在C++中,typedef的使用和C中是一樣的:

typedef struct Number{      //去掉Number也對
    int a;
    int b;
}Num;                       //Num是一個結(jié)構(gòu)體類型寄月,Num=struct Number.                    
Num num1;                   //使用時需要先聲明結(jié)構(gòu)體變量
num1.a=10;                  //再訪問成員變量

在C++中還有一種更簡便的使用方法:

struct Number{
    int a;
    int b;
}Num;                       //Num是一個結(jié)構(gòu)體變量!!!!               
Num.a=10;                   //使用時可以直接訪問成員變量

終于進入對象環(huán)節(jié)了

這里大家簡單過下辜膝,接觸過java面向?qū)ο蟮耐瑢W這里可以一秒掃過,遇到問題再回頭查驗漾肮。

類和對象内舟、C++ 類的定義

class Box {
   public:
  double length;   // Length of a box
  double breadth;  // Breadth of a box
  double height;   // Height of a box
};

訪問數(shù)據(jù)成員

類的對象的公共數(shù)據(jù)成員可以使用直接成員訪問操作符 . 訪問.

類與對象的細節(jié)

類與對象的細節(jié).png

繼承

在面向?qū)ο缶幊讨凶钪匾母拍钪痪褪抢^承。繼承允許我們根據(jù)一個類來定義另一個類初橘,這使得創(chuàng)建和維護一
個應(yīng)用程序更加的容易。這也提供了一個重用代碼功能和快速實現(xiàn)的機會充岛。
當創(chuàng)建一個類保檐,不是寫全新的數(shù)據(jù)成員和成員函數(shù)的時候,程序員可以指定新類崔梗,這個類可以繼承現(xiàn)有類的成
員夜只。這個現(xiàn)有的類稱為基類,這個新類稱為派生類蒜魄。
繼承的概念其實是一種關(guān)系扔亥。例如场躯,哺乳動物是動物,狗是哺乳動物旅挤,因此狗是動物等等踢关。

基類和派生類

一個類可以繼承多個類,這就意味著它可以從多個基類中繼承數(shù)據(jù)和函數(shù)粘茄。為了定義一個派生類签舞,我們可以使用
一個類繼承列表來指定基類。一個類繼承列表指定一個或多個基類柒瓣,類繼承列表形式如下:

class derived-class: access-specifier base-class

在這里 access-specifier 是 public 儒搭、 protected 或者 private ,base-class 是之前定義的類的名稱芙贫。如果 不使用 access-specifier 搂鲫,那么在默認情況下它是私有的。
考慮一個基類的 shape 和其派生類 Rectangle 的繼承情況如下:

#include <iostream>
using namespace std;
// Base class
class Shape
{
   public:
  void setWidth(int w)
  {
width = w; }
  void setHeight(int h)
{
height = h;
} protected:
  int width;
  int height;
};
// Derived class
class Rectangle: public Shape
{
   public:
  int getArea()
  {
 return (width * height);
  }
};
int main(void)
{
   Rectangle Rect;
   Rect.setWidth(5);
   Rect.setHeight(7);
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;
return 0; }
上面的代碼編譯和執(zhí)行時磺平,它產(chǎn)生以下結(jié)果:
Total area: 35

繼承方式

當從一個基類派生一個子類的時候,公共基類可以通過 public 魂仍,protected ,或者 private 方式被繼承褪秀。繼承 方式被 access-specifier 指定蓄诽,正如上面解釋的。
我們幾乎不使用protected或私有private 繼承媒吗,但public繼承是常用的仑氛。在使用不同類型的繼承的時候,應(yīng)用規(guī) 則如下:
? public 繼承:當從一個公有基類派生一個類的時候,基類的公有成員成為派生類的公有成員;基類的保護成 員成為派生類的保護成員闸英。一個基類的私有成員不能被派生類直接訪問锯岖,但可以通過調(diào)用基類的公有和保護 成員訪問基類的私有成員。
? protected 繼承:當從一個受保護的基類派生子類的時候,基類的公有和保護成員成為派生類的保護成員甫何。
? private 繼承:當從一個私有的基類派生子類的時候,基類的公有和保護成員成為派生類的私有成員出吹。

多繼承

一個C++類可以繼承多個類的成員,多繼承語法如下:
class derived-class: access baseA, access baseB....
在這里 access 是 public 辙喂,protected 捶牢,或者是 private ,并且每一個基類將有一個 access 類型巍耗,他們將由 逗號分隔開秋麸,如上所示。讓我們試試下面的例子:

#include <iostream>
using namespace std;
// Base class Shape
class Shape
{
   public:
  void setWidth(int w)
  {
width = w; }
  void setHeight(int h)
  {
  height = h; }
   protected:
  int width;
  int height;
};
// Base class PaintCost
class PaintCost
{
   public:
  int getCost(int area)
  {
 return area * 70;
  }
};
// Derived class
class Rectangle: public Shape, public PaintCost
{
   public:
  int getArea()
  {
 return (width * height);
  }
};
int main(void)
{
   Rectangle Rect;
   int area;
   Rect.setWidth(5);
   Rect.setHeight(7);
   area = Rect.getArea();
   // Print the area of the object.
   cout << "Total area: " << Rect.getArea() << endl;
   // Print the total cost of painting
   cout << "Total paint cost: $" << Rect.getCost(area) << endl;
return 0; }
上面的代碼編譯和執(zhí)行時炬太,它產(chǎn)生以下結(jié)果:
Total area: 35
Total paint cost: $2450

C++ 中的函數(shù)重載

C++ 允許在同一范圍內(nèi)對一個函數(shù)名或一個操作符指定多個定義灸蟆,分別被稱為函數(shù)重載和操作符重載。
重載聲明是在同一的范圍內(nèi)對先前已經(jīng)聲明的相同函數(shù)名的聲明亲族,除非這兩個聲明有不同的參數(shù)和明顯不同的定
義(實現(xiàn)方式)炒考。
當你調(diào)用一個重載的函數(shù)或操作符時可缚,編譯器通過比較用來調(diào)用函數(shù)或操作符的指定的參數(shù)類型來確定使用最合
適的定義。選擇最合適的重載函數(shù)或操作符的過程被稱為重載決議斋枢。
你可以在同一范圍內(nèi)對同一函數(shù)名有多個定義帘靡。函數(shù)的定義必須滿足參數(shù)類型不同或參數(shù)的數(shù)量不同或兩者都不
相同。你不能重載只有返回類型不同的函數(shù)聲明杏慰。

#include <iostream>
using namespace std;
class printData
{
   public:
  void print(int i) {
cout << "Printing int: " << i << endl;
  }
  void print(double  f) {
cout << "Printing float: " << f << endl;
}
  void print(char* c) {
cout << "Printing character: " << c << endl;
} };
int main(void)
{
   printData pd;
   // Call print to print integer
pd.print(5);
   // Call print to print float
   pd.print(500.263);
   // Call print to print character
   pd.print("Hello C++");
return 0; }
上面的代碼編譯和執(zhí)行時测柠,它產(chǎn)生以下結(jié)果:
Printing int: 5
Printing float: 500.263
Printing character: Hello C++

C++ 中的運算符重載

你可以重新定義或重載的大部分 C++ 已有的操作符。因此缘滥,程序員可以像使用用戶自定義類型一樣使用操作 符轰胁。
重載操作符是一類函數(shù),它們就是對已有的運算符重新進行定義朝扼,賦予其另一種功能赃阀,以適應(yīng)不同的數(shù)據(jù)類 型。像任何其它函數(shù),重載運算符也有返回類型和參數(shù)列表擎颖。
C++ 中的運算符重載

Box operator+(const Box&);

聲明加法運算符可以用來使兩個 Box 對象相加并返回最終 Box 對象榛斯。大多數(shù)重載運算符可以被定義為普通非成 員函數(shù)或類成員函數(shù)。如果我們把上面的函數(shù)定義為一個類的非成員函數(shù),那么我們就必須為每個操作數(shù)傳兩個參 數(shù)如下:

Box operator+(const Box&, const Box&);

下面是通過使用成員函數(shù)來展示運算符重載的概念的示例搂捧。這里一個對象作為一個參數(shù)被傳遞驮俗,通過訪問這個對 象可以獲得參數(shù)的屬性,將調(diào)用這個操作符的對象可以通過使用 this 操作符獲得允跑,下面這個例子展示了這一 點:

#include <iostream>
using namespace std;
class Box {
public:
    double getVolume(void)
  {
 return length * breadth * height;
  }
  void setLength( double len )
  {
  length = len;
  }
  void setBreadth( double bre )
  {
  breadth = bre;
  }
  void setHeight( double hei )
  {
  height = hei;
  }
  // Overload + operator to add two Box objects.
  Box operator+(const Box& b)
  {
 Box box;
 box.length = this->length + b.length;
 box.breadth = this->breadth + b.breadth;
 box.height = this->height + b.height;
 return box;
} private:
  double length;  // Length of a box
  double breadth; // Breadth of a box
  double height;  // Height of a box
};
// Main function for the program
int main( )
{
   Box Box1;// Declare Box1 of type Box
   Box Box2;// Declare Box2 of type Box
   Box Box3;// Declare Box3 of type Box
   double volume = 0.0; // Store the volume of a box here
   // box 1 specification
   Box1.setLength(6.0);
   Box1.setBreadth(7.0);
   Box1.setHeight(5.0);
// box 2 specification
   Box2.setLength(12.0);
   Box2.setBreadth(13.0);
   Box2.setHeight(10.0);
   // volume of box 1
   volume = Box1.getVolume();
   cout << "Volume of Box1 : " << volume <<endl;
   // volume of box 2
   volume = Box2.getVolume();
   cout << "Volume of Box2 : " << volume <<endl;
   // Add two object as follows:
   Box3 = Box1 + Box2;
   // volume of box 3
   volume = Box3.getVolume();
   cout << "Volume of Box3 : " << volume <<endl;
return 0; }
上面的代碼編譯和執(zhí)行時王凑,它產(chǎn)生以下結(jié)果:
Volume of Box1 : 210
Volume of Box2 : 1560
Volume of Box3 : 5400

可重載/不可重載的運算符

可以重載的運算符.png

不可以重載的運算符

不可以重載的運算符.png

多態(tài)

面向?qū)ο蠓浅V匾囊粋€概念:多態(tài)性意味著有多種形式。通常聋丝,多態(tài)發(fā)生在類之間存在層級關(guān)系且這些類有繼承關(guān)系的時候索烹。 C++ 多態(tài)性是指不同的對象發(fā)送同一個消息,不同對象對應(yīng)同一消息產(chǎn)生不同行為弱睦。 考慮下面的例子百姓,一個基類派生了其他的兩類:

#include <iostream>
using namespace std;
class Shape {
   protected:
  int width, height;
   public:
  Shape( int a=0, int b=0)
  {
 width = a;
 height = b;
}
int area() {
 cout << "Parent class area :" <<endl;
 return 0;
} };
class Rectangle: public Shape{
   public:
  Rectangle( int a=0, int b=0):Shape(a, b) { }
  int area ()
  {
 cout << "Rectangle class area :" <<endl;
 return (width * height);
} };
class Triangle: public Shape{
   public:
  Triangle( int a=0, int b=0):Shape(a, b) { }
  int area ()
  {
 cout << "Triangle class area :" <<endl;
 return (width * height / 2);
}
};
// Main function for the program
int main( )
{
   Shape *shape;
   Rectangle rec(10,7);
   Triangle  tri(10,5);
   // store the address of Rectangle
   shape = &rec;
   // call rectangle area.
   shape->area();
   // store the address of Triangle
   shape = &tri;
   // call triangle area.
   shape->area();
return 0; }
上面的代碼編譯和執(zhí)行時,它產(chǎn)生以下結(jié)果:
Parent class area
Parent class area

輸出結(jié)果不正確的原因是對函數(shù) area() 的調(diào)用被編譯器設(shè)置了一次况木,即在基類中定義的版本垒拢,這被稱為對函數(shù) 調(diào)用的靜態(tài)分辨或者靜態(tài)鏈接,靜態(tài)鏈接就是在程序被執(zhí)行之前函數(shù)調(diào)用是確定的火惊。這有時也被稱為早期綁 定子库,因為函數(shù) area() 在編譯程序期間是固定的。
但是現(xiàn)在矗晃,讓我們對程序做略微修改,并在 Shape 類中 area() 的聲明之前加關(guān)鍵字 virtual 宴倍,它看起來像這 樣:

class Shape {
   protected:
  int width, height;
   public:
  Shape( int a=0, int b=0)
  {
 width = a;
 height = b;
  }
  virtual int area()
  {
cout << "Parent class area :" <<endl;
return 0; }
};
這輕微的修改后张症,前面的示例代碼編譯和執(zhí)行時仓技,它會產(chǎn)生以下結(jié)果:
Rectangle class area
Triangle class area

這一次,編譯器關(guān)注的是指針的內(nèi)容而不是它的類型俗他。因此脖捻,由于三角形和矩形類對象的地址被存儲在形狀類 中,各自的 area() 函數(shù)可以被調(diào)用兆衅。
正如你所看到的地沮,每個子類都有一個對 area() 函數(shù)的實現(xiàn)。通常多態(tài)就是這樣使用的羡亩。你有不同的類摩疑,它們都 有一個的相同名字的函數(shù),甚至有相同的參數(shù)畏铆,但是對這個函數(shù)有不同的實現(xiàn)雷袋。

虛函數(shù)

基類中的虛函數(shù)是一個使用關(guān)鍵字 virtual 聲明的函數(shù)。派生類中已經(jīng)對函數(shù)進行定義的情況下辞居,定義一個基類 的虛函數(shù)楷怒,就是要告訴編譯器我們不想對這個函數(shù)進行靜態(tài)鏈接。
我們所希望的是根據(jù)調(diào)用函數(shù)的對象的類型對程序中在任何給定指針中被調(diào)用的函數(shù)的選擇瓦灶。這種操作被稱為動
態(tài)鏈接鸠删,或者后期綁定。

純虛函數(shù)

可能你想把虛函數(shù)包括在基類中贼陶,以便它可以在派生類中根據(jù)該類的對象對函數(shù)進行重新定義刃泡,但在許多情況下,在基類中不能對虛函數(shù)給出有意義的實現(xiàn)每界。
我們可以改變基類中的虛函數(shù) area() 如下:

class Shape {
   protected:
  int width, height;
   public:
  Shape( int a=0, int b=0)
  {
 width = a;
 height = b;
  }
  // pure virtual function
  virtual int area() = 0;
};
area() = 0

就是告訴編譯器上面的函數(shù)沒有函數(shù)體捅僵。上面的虛函數(shù)就被稱為純虛函數(shù)。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末眨层,一起剝皮案震驚了整個濱河市庙楚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌趴樱,老刑警劉巖馒闷,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異叁征,居然都是意外死亡纳账,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門捺疼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疏虫,“玉大人,你說我怎么就攤上這事∥悦兀” “怎么了呢袱?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長翅敌。 經(jīng)常有香客問我羞福,道長,這世上最難降的妖魔是什么蚯涮? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任治专,我火速辦了婚禮,結(jié)果婚禮上遭顶,老公的妹妹穿的比我還像新娘张峰。我一直安慰自己,他們只是感情好液肌,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布挟炬。 她就那樣靜靜地躺著,像睡著了一般嗦哆。 火紅的嫁衣襯著肌膚如雪谤祖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天老速,我揣著相機與錄音粥喜,去河邊找鬼。 笑死橘券,一個胖子當著我的面吹牛额湘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播旁舰,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锋华,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了箭窜?” 一聲冷哼從身側(cè)響起毯焕,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎磺樱,沒想到半個月后纳猫,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡竹捉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年芜辕,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片块差。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡侵续,死狀恐怖倔丈,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情询兴,我是刑警寧澤乃沙,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站诗舰,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏训裆。R本人自食惡果不足惜眶根,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望边琉。 院中可真熱鬧属百,春花似錦、人聲如沸变姨。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽定欧。三九已至渔呵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間砍鸠,已是汗流浹背扩氢。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留爷辱,地道東北人录豺。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像饭弓,于是被迫代替她去往敵國和親双饥。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353