C++類&對象

一 定義 C++ 對象

類提供了對象的藍圖,所以基本上,對象是根據類來創建的。聲明類的對象,就像聲明基本類型的變量一樣。下面的語句聲明瞭類 Box 的兩個對象:

Box Box1;          // 聲明 Box1,類型爲 Box
Box Box2;          // 聲明 Box2,類型爲 Box

對象 Box1 和 Box2 都有它們各自的數據成員。

二 訪問數據成員

類的對象的公共數據成員可以使用直接成員訪問運算符 (.) 來訪問。爲了更好地理解這些概念,讓我們嘗試一下下面的實例:

#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;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Box1 的體積:210
Box2 的體積:1560

三 定義 C++ 對象

類提供了對象的藍圖,所以基本上,對象是根據類來創建的。聲明類的對象,就像聲明基本類型的變量一樣。下面的語句聲明瞭類 Box 的兩個對象:

Box Box1;          // 聲明 Box1,類型爲 Box
Box Box2;          // 聲明 Box2,類型爲 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;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Box1 的體積:210
Box2 的體積:1560

需要注意的是,私有的成員和受保護的成員不能使用直接成員訪問運算符 (.) 來直接訪問。我們將在後續的教程中學習如何訪問私有成員和受保護的成員。


需要注意的是,私有的成員和受保護的成員不能使用直接成員訪問運算符 (.) 來直接訪問。我們將在後續的教程中學習如何訪問私有成員和受保護的成員。

四 類 & 對象詳解

到目前爲止,我們已經對 C++ 的類和對象有了基本的瞭解。下面的列表中還列出了其他一些 C++ 類和對象相關的概念,可以點擊相應的鏈接進行學習。

概念 描述
類成員函數 類的成員函數是指那些把定義和原型寫在類定義內部的函數,就像類定義中的其他變量一樣。
類訪問修飾符 類成員可以被定義爲 public、private 或 protected。默認情況下是定義爲 private。
構造函數 & 析構函數 類的構造函數是一種特殊的函數,在創建一個新的對象時調用。類的析構函數也是一種特殊的函數,在刪除所創建的對象時調用。
C++ 拷貝構造函數 拷貝構造函數,是一種特殊的構造函數,它在創建對象時,是使用同一類中之前創建的對象來初始化新創建的對象。
C++ 友元函數 友元函數可以訪問類的 private 和 protected 成員。
C++ 內聯函數 通過內聯函數,編譯器試圖在調用函數的地方擴展函數體中的代碼。
C++ 中的 this 指針 每個對象都有一個特殊的指針 this,它指向對象本身。
C++ 中指向類的指針 指向類的指針方式如同指向結構的指針。實際上,類可以看成是一個帶有函數的結構。
C++ 類的靜態成員 類的數據成員和函數成員都可以被聲明爲靜態的。

1、類成員函數

類的成員函數是指那些把定義和原型寫在類定義內部的函數,就像類定義中的其他變量一樣。類成員函數是類的一個成員,它可以操作類的任意對象,可以訪問對象中的所有成員。

讓我們看看之前定義的類 Box,現在我們要使用成員函數來訪問類的成員,而不是直接訪問這些類的成員:

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

成員函數可以定義在類定義內部,或者單獨使用範圍解析運算符 :: 來定義。在類定義中定義的成員函數把函數聲明爲內聯的,即便沒有使用 inline 標識符。所以您可以按照如下方式定義 Volume() 函數:

class Box
{
   public:
      double length;      // 長度
      double breadth;     // 寬度
      double height;      // 高度
   
      double getVolume(void)
      {
         return length * breadth * height;
      }
};

您也可以在類的外部使用範圍解析運算符 :: 定義該函數,如下所示:

double Box::getVolume(void)
{
    return length * breadth * height;
}

在這裏,需要強調一點,在 :: 運算符之前必須使用類名。調用成員函數是在對象上使用點運算符(.),這樣它就能操作與該對象相關的數據,如下所示:

Box myBox;          // 創建一個對象

myBox.getVolume();  // 調用該對象的成員函數

讓我們使用上面提到的概念來設置和獲取類中不同的成員的值:

#include <iostream>

using namespace std;

class Box
{
   public:
      double length;         // 長度
      double breadth;        // 寬度
      double height;         // 高度

      // 成員函數聲明
      double getVolume(void);
      void setLength( double len );
      void setBreadth( double bre );
      void setHeight( double hei );
};

// 成員函數定義
double Box::getVolume(void)
{
    return length * breadth * height;
}

void Box::setLength( double len )
{
    length = len;
}

void Box::setBreadth( double bre )
{
    breadth = bre;
}

void Box::setHeight( double hei )
{
    height = hei;
}

// 程序的主函數
int main( )
{
   Box Box1;                // 聲明 Box1,類型爲 Box
   Box Box2;                // 聲明 Box2,類型爲 Box
   double volume = 0.0;     // 用於存儲體積
 
   // box 1 詳述
   Box1.setLength(6.0); 
   Box1.setBreadth(7.0); 
   Box1.setHeight(5.0);

   // box 2 詳述
   Box2.setLength(12.0); 
   Box2.setBreadth(13.0); 
   Box2.setHeight(10.0);

   // box 1 的體積
   volume = Box1.getVolume();
   cout << "Box1 的體積:" << volume <<endl;

   // box 2 的體積
   volume = Box2.getVolume();
   cout << "Box2 的體積:" << volume <<endl;
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Box1 的體積: 210
Box2 的體積: 1560

2、類訪問修飾符

數據隱藏是面向對象編程的一個重要特點,它防止函數直接訪問類類型的內部成員。類成員的訪問限制是通過在類主體內部對各個區域標記 public、private、protected 來指定的。關鍵字 public、private、protected 稱爲訪問說明符。

一個類可以有多個 public、protected 或 private 標記區域。每個標記區域在下一個標記區域開始之前或者在遇到類主體結束右括號之前都是有效的。成員和類的默認訪問修飾符是 private。

class Base {
 
   public:
 
  // public members go here
 
   protected:
 
  // protected members go here
 
   private:
 
  // private members go here
 
};

公有(public)成員

公有成員在程序中類的外部是可訪問的。您可以不使用任何成員函數來設置和獲取公有變量的值,如下所示:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      double length;
      void setLength( double len );
      double getLength( void );
};
 
// 成員函數定義
double Line::getLength(void)
{
    return length ;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
// 程序的主函數
int main( )
{
   Line line;
 
   // 設置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   // 不使用成員函數設置長度
   line.length = 10.0; // OK: 因爲 length 是公有的
   cout << "Length of line : " << line.length <<endl;
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Length of line : 6
Length of line : 10

私有(private)成員

私有成員變量或函數在類的外部是不可訪問的,甚至是不可查看的。只有類和友元函數可以訪問私有成員。

默認情況下,類的所有成員都是私有的。例如在下面的類中,width 是一個私有成員,這意味着,如果您沒有使用任何訪問修飾符,類的成員將被假定爲私有成員:

class Box
{
   double width;
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
};
 

實際操作中,我們一般會在私有區域定義數據,在公有區域定義相關的函數,以便在類的外部也可以調用這些函數,如下所示:

#include <iostream>
 
using namespace std;
 
class Box
{
   public:
      double length;
      void setWidth( double wid );
      double getWidth( void );
 
   private:
      double width;
};
 
// 成員函數定義
double Box::getWidth(void)
{
    return width ;
}
 
void Box::setWidth( double wid )
{
    width = wid;
}
 
// 程序的主函數
int main( )
{
   Box box;
 
   // 不使用成員函數設置長度
   box.length = 10.0; // OK: 因爲 length 是公有的
   cout << "Length of box : " << box.length <<endl;
 
   // 不使用成員函數設置寬度
   // box.width = 10.0; // Error: 因爲 width 是私有的
   box.setWidth(10.0);  // 使用成員函數設置寬度
   cout << "Width of box : " << box.getWidth() <<endl;
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Length of box : 10
Width of box : 10

保護(protected)成員

保護成員變量或函數與私有成員十分相似,但有一點不同,保護成員在派生類(即子類)中是可訪問的。

在下一個章節中,您將學習到派生類和繼承的知識。現在您可以看到下面的實例中,我們從父類 Box 派生了一個子類 smallBox

下面的實例與前面的實例類似,在這裏 width 成員可被派生類 smallBox 的任何成員函數訪問。

#include <iostream>
using namespace std;
 
class Box
{
   protected:
      double width;
};
 
class SmallBox:Box // SmallBox 是派生類
{
   public:
      void setSmallWidth( double wid );
      double getSmallWidth( void );
};
 
// 子類的成員函數
double SmallBox::getSmallWidth(void)
{
    return width ;
}
 
void SmallBox::setSmallWidth( double wid )
{
    width = wid;
}
 
// 程序的主函數
int main( )
{
   SmallBox box;
 
   // 使用成員函數設置寬度
   box.setSmallWidth(5.0);
   cout << "Width of box : "<< box.getSmallWidth() << endl;
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Width of box : 5

3、類構造函數 & 析構函數

類的構造函數

類的構造函數是類的一種特殊的成員函數,它會在每次創建類的新對象時執行。

構造函數的名稱與類的名稱是完全相同的,並且不會返回任何類型,也不會返回 void。構造函數可用於爲某些成員變量設置初始值。

下面的實例有助於更好地理解構造函數的概念:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();  // 這是構造函數
 
   private:
      double length;
};
 
// 成員函數定義,包括構造函數
Line::Line(void)
{
    cout << "Object is being created" << endl;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函數
int main( )
{
   Line line;
 
   // 設置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Object is being created
Length of line : 6

帶參數的構造函數

默認的構造函數沒有任何參數,但如果需要,構造函數也可以帶有參數。這樣在創建對象時就會給對象賦初始值,如下面的例子所示:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line(double len);  // 這是構造函數
 
   private:
      double length;
};
 
// 成員函數定義,包括構造函數
Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}
 
void Line::setLength( double len )
{
    length = len;
}
 
double Line::getLength( void )
{
    return length;
}
// 程序的主函數
int main( )
{
   Line line(10.0);
 
   // 獲取默認設置的長度
   cout << "Length of line : " << line.getLength() <<endl;
   // 再次設置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Object is being created, length = 10
Length of line : 10
Length of line : 6

使用初始化列表來初始化字段

使用初始化列表來初始化字段:

Line::Line( double len): length(len)
{
    cout << "Object is being created, length = " << len << endl;
}

上面的語法等同於如下語法:

Line::Line( double len)
{
    cout << "Object is being created, length = " << len << endl;
    length = len;
}

假設有一個類 C,具有多個字段 X、Y、Z 等需要進行初始化,同理地,您可以使用上面的語法,只需要在不同的字段使用逗號進行分隔,如下所示:

C::C( double a, double b, double c): X(a), Y(b), Z(c)
{
  ....
}

類的析構函數

類的析構函數是類的一種特殊的成員函數,它會在每次刪除所創建的對象時執行。

析構函數的名稱與類的名稱是完全相同的,只是在前面加了個波浪號(~)作爲前綴,它不會返回任何值,也不能帶有任何參數。析構函數有助於在跳出程序(比如關閉文件、釋放內存等)前釋放資源。

下面的實例有助於更好地理解析構函數的概念:

#include <iostream>
 
using namespace std;
 
class Line
{
   public:
      void setLength( double len );
      double getLength( void );
      Line();   // 這是構造函數聲明
      ~Line();  // 這是析構函數聲明
 
   private:
      double length;
};
 
// 成員函數定義,包括構造函數
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;
}
// 程序的主函數
int main( )
{
   Line line;
 
   // 設置長度
   line.setLength(6.0); 
   cout << "Length of line : " << line.getLength() <<endl;
 
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

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

拷貝構造函數

拷貝構造函數是一種特殊的構造函數,它在創建對象時,是使用同一類中之前創建的對象來初始化新創建的對象。拷貝構造函數通常用於:

  • 通過使用另一個同類型的對象來初始化新創建的對象。

  • 複製對象把它作爲參數傳遞給函數。

  • 複製對象,並從函數返回這個對象。

如果在類中沒有定義拷貝構造函數,編譯器會自行定義一個。如果類帶有指針變量,並有動態內存分配,則它必須有一個拷貝構造函數。拷貝構造函數的最常見形式如下:

classname (const classname &obj) {
   // 構造函數的主體
}

在這裏,obj 是一個對象引用,該對象是用於初始化另一個對象的。

#include <iostream>

using namespace std;

class Line
{
   public:
      int getLength( void );
      Line( int len );             // 簡單的構造函數
      Line( const Line &obj);  // 拷貝構造函數
      ~Line();                     // 析構函數

   private:
      int *ptr;
};

// 成員函數定義,包括構造函數
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // 爲指針分配內存
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
   *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// 程序的主函數
int main( )
{
   Line line(10);

   display(line);

   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Normal constructor allocating ptr
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
Freeing memory!

下面的實例對上面的實例稍作修改,通過使用已有的同類型的對象來初始化新創建的對象:

#include <iostream>

using namespace std;

class Line
{
   public:
      int getLength( void );
      Line( int len );             // 簡單的構造函數
      Line( const Line &obj);  // 拷貝構造函數
      ~Line();                     // 析構函數

   private:
      int *ptr;
};

// 成員函數定義,包括構造函數
Line::Line(int len)
{
    cout << "Normal constructor allocating ptr" << endl;
    // 爲指針分配內存
    ptr = new int;
    *ptr = len;
}

Line::Line(const Line &obj)
{
    cout << "Copy constructor allocating ptr." << endl;
    ptr = new int;
   *ptr = *obj.ptr; // copy the value
}

Line::~Line(void)
{
    cout << "Freeing memory!" << endl;
    delete ptr;
}
int Line::getLength( void )
{
    return *ptr;
}

void display(Line obj)
{
   cout << "Length of line : " << obj.getLength() <<endl;
}

// 程序的主函數
int main( )
{
   Line line1(10);

   Line line2 = line1; // 這裏也調用了拷貝構造函數

   display(line1);
   display(line2);

   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

/*Line Line(10)對應*/Normal constructor allocating ptr
/*Line Line2 = Line1對應*/Copy constructor allocating ptr.
/*display(Line1)對應*/
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
/*display(Line2)對應*/
Copy constructor allocating ptr.
Length of line : 10
Freeing memory!
/*Line Line2 = Line1對應*/
Freeing memory!
/*Line Line(10)對應*/
Freeing memory!
由上述例子可以看出:構造該函數和拷貝構造函數的構造和析構順序正好相反,最後構造的最先析構;

 友元函數

類的友元函數是定義在類外部,但有權訪問類的所有私有(private)成員和保護(protected)成員。儘管友元函數的原型有在類的定義中出現過,但是友元函數並不是成員函數。

友元可以是一個函數,該函數被稱爲友元函數;友元也可以是一個類,該類被稱爲友元類,在這種情況下,整個類及其所有成員都是友元。

如果要聲明函數爲一個類的友元,需要在類定義中該函數原型前使用關鍵字 friend,如下所示:

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

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

friend class ClassTwo;

請看下面的程序:

#include <iostream>
 
using namespace std;
 
class Box
{
   double width;
public:
   friend void printWidth( Box box );
   void setWidth( double wid );
};

// 成員函數定義
void Box::setWidth( double wid )
{
    width = wid;
}

// 請注意:printWidth() 不是任何類的成員函數
void printWidth( Box box )
{
   /* 因爲 printWidth() 是 Box 的友元,它可以直接訪問該類的任何成員 */
   cout << "Width of box : " << box.width <<endl;
}
 
// 程序的主函數
int main( )
{
   Box box;
 
   // 不使用成員函數設置寬度
   box.setWidth(10.0);
   
   // 使用友元函數輸出寬度
   printWidth( box );
 
   return 0;
}

內聯函數

C++ 內聯函數是通常與類一起使用。如果一個函數是內聯的,那麼在編譯時,編譯器會把該函數的代碼副本放置在每個調用該函數的地方。

對內聯函數進行任何修改,都需要重新編譯函數的所有客戶端,因爲編譯器需要重新更換一次所有的代碼,否則將會繼續使用舊的函數。

如果想把一個函數定義爲內聯函數,則需要在函數名前面放置關鍵字 inline,在調用函數之前需要對函數進行定義。如果已定義的函數多於一行,編譯器會忽略 inline 限定符。的情況下定義的函數多了一行。

在類定義中的定義的函數都是內聯函數,即使沒有使用 inline 說明符

下面是一個實例,使用內聯函數來返回兩個數中的最大值:

#include <iostream>
 
using namespace std;

inline int Max(int x, int y)
{
   return (x > y)? x : y;
}

// 程序的主函數
int main( )
{

   cout << "Max (20,10): " << Max(20,10) << endl;
   cout << "Max (0,200): " << Max(0,200) << endl;
   cout << "Max (100,1010): " << Max(100,1010) << endl;
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Max (20,10): 20
Max (0,200): 200
Max (100,1010): 1010

this 指針

在 C++ 中,每一個對象都能通過 this 指針來訪問自己的地址。this 指針是所有成員函數的隱含參數。因此,在成員函數內部,它可以用來指向調用對象。

友元函數沒有 this 指針,因爲友元不是類的成員。只有成員函數纔有 this 指針

下面的實例有助於更好地理解 this 指針的概念:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      // 構造函數定義
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      int compare(Box box)
      {
         return this->Volume() > box.Volume();
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2

   if(Box1.compare(Box2))
   {
      cout << "Box2 is smaller than Box1" <<endl;
   }
   else
   {
      cout << "Box2 is equal to or larger than Box1" <<endl;
   }
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Constructor called.
Constructor called.
Box2 is equal to or larger than Box1

指向類的指針

一個指向 C++ 類的指針與指向結構的指針類似,訪問指向類的指針的成員,需要使用成員訪問運算符 ->,就像訪問指向結構的指針一樣。與所有的指針一樣,您必須在使用指針之前,對指針進行初始化。

下面的實例有助於更好地理解指向類的指針的概念:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      // 構造函數定義
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // Length of a box
      double breadth;    // Breadth of a box
      double height;     // Height of a box
};

int main(void)
{
   Box Box1(3.3, 1.2, 1.5);    // Declare box1
   Box Box2(8.5, 6.0, 2.0);    // Declare box2
   Box *ptrBox;                // Declare pointer to a class.

   // 保存第一個對象的地址
   ptrBox = &Box1;

   // 現在嘗試使用成員訪問運算符來訪問成員
   cout << "Volume of Box1: " << ptrBox->Volume() << endl;

   // 保存第二個對象的地址
   ptrBox = &Box2;

   // 現在嘗試使用成員訪問運算符來訪問成員
   cout << "Volume of Box2: " << ptrBox->Volume() << endl;
  
   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Constructor called.
Constructor called.
Volume of Box1: 5.94
Volume of Box2: 102

類的靜態成員

我們可以使用 static 關鍵字來把類成員定義爲靜態的。當我們聲明類的成員爲靜態時,這意味着無論創建多少個類的對象,靜態成員都只有一個副本。

靜態成員在類的所有對象中是共享的。如果不存在其他的初始化語句,在創建第一個對象時,所有的靜態數據都會被初始化爲零。我們不能把靜態成員放置在類的定義中,但是可以在類的外部通過使用範圍解析運算符 :: 來重新聲明靜態變量從而對它進行初始化,如下面的實例所示。

下面的實例有助於更好地理解靜態數據成員的概念:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      static int objectCount;
      // 構造函數定義
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次創建對象時增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
   private:
      double length;     // 長度
      double breadth;    // 寬度
      double height;     // 高度
};

// 初始化類 Box 的靜態成員
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

   // 輸出對象的總數
   cout << "Total objects: " << Box::objectCount << endl;

   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Constructor called.
Constructor called.
Total objects: 2

靜態函數成員

如果把函數成員聲明爲靜態的,就可以把函數與類的任何特定對象獨立開來。靜態成員函數即使在類對象不存在的情況下也能被調用,靜態函數只要使用類名加範圍解析運算符 :: 就可以訪問

靜態成員函數只能訪問靜態數據成員,不能訪問其他靜態成員函數和類外部的其他函數

靜態成員函數有一個類範圍,他們不能訪問類的 this 指針。您可以使用靜態成員函數來判斷類的某些對象是否已被創建。

下面的實例有助於更好地理解靜態函數成員的概念:

#include <iostream>
 
using namespace std;

class Box
{
   public:
      static int objectCount;
      // 構造函數定義
      Box(double l=2.0, double b=2.0, double h=2.0)
      {
         cout <<"Constructor called." << endl;
         length = l;
         breadth = b;
         height = h;
         // 每次創建對象時增加 1
         objectCount++;
      }
      double Volume()
      {
         return length * breadth * height;
      }
      static int getCount()
      {
         return objectCount;
      }
   private:
      double length;     // 長度
      double breadth;    // 寬度
      double height;     // 高度
};

// 初始化類 Box 的靜態成員
int Box::objectCount = 0;

int main(void)
{
  
   // 在創建對象之前輸出對象的總數
   cout << "Inital Stage Count: " << Box::getCount() << endl;

   Box Box1(3.3, 1.2, 1.5);    // 聲明 box1
   Box Box2(8.5, 6.0, 2.0);    // 聲明 box2

   // 在創建對象之後輸出對象的總數
   cout << "Final Stage Count: " << Box::getCount() << endl;

   return 0;
}

當上面的代碼被編譯和執行時,它會產生下列結果:

Inital Stage Count: 0
Constructor called.
Constructor called.
Final Stage Count: 2

發佈了28 篇原創文章 · 獲贊 8 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章