C++---CHAPTER 7: CLASS

  • 引入this
    調(diào)用一個成員函數(shù),編譯器用請求該函數(shù)的對象地址初始化this,所以this的目的總是指向這個對象,因此this是一個常量指針。

  • 引入const成員函數(shù)
    以下是Sales_data類的一個成員函數(shù)的定義,參數(shù)列表之后的const作用是修改隱式this指針的類型,因為默認情況下,this的類型是指向類類型非常量版本的常量指針。所以默認情況不能把this綁定到一個常量對象上。這樣使用const的成員函數(shù)被稱為常量成員函數(shù)。

std::string isbn() const {return bookNo;}
  • 類作用域
    編譯器首先編譯成員的聲明,然后是成員函數(shù)體,所以成員函數(shù)體可以隨意使用類中的其他成員無須在意成員的順序。

  • 定義一個返回this對象的函數(shù)
    函數(shù)類似于某個內(nèi)置運算符時,應(yīng)該令該函數(shù)的行為盡量模仿這個運算符。內(nèi)置賦值運算符把它的左側(cè)運算對當左值返回,意味著這些函數(shù)返回的是對象本身而非對象的副本,因此combine必須返回引用類型。

Sales_data& Sales_data::combine(const Sales_data &rhs)
{
  units_sold += rhs.units_sold;
  revenue += rhs.revenue;
  return *this;  //解引用指針獲取執(zhí)行該函數(shù)的對象。
}
  • 類相關(guān)的非成員函數(shù)
    如果函數(shù)在概念上屬于類但是不定義在類中,則它一般應(yīng)與類聲明在同一個頭文件。
    默認情況下拷貝類的對象,拷貝的是對象的數(shù)據(jù)成員。
  • 構(gòu)造函數(shù)
    構(gòu)造函數(shù)不能聲明為const,直到構(gòu)造函數(shù)完成初始化過程,對象才能取得"常量"屬性。因此,構(gòu)造函數(shù)在const對象的構(gòu)造過程中可以向其寫值。
    • 合成的默認構(gòu)造函數(shù):類沒有顯示的定義構(gòu)造函數(shù),那么編譯器會為我們隱式地定義一個合成的默認構(gòu)造函數(shù),安照類內(nèi)初始值初始化成員,沒有的話則默認初始化成員。只有當類沒有聲明任何構(gòu)造函數(shù)的時候,才會默認構(gòu)造函數(shù)。使用= default要求編譯器生成構(gòu)造函數(shù)。

    • 構(gòu)造函數(shù)初始值列表:

Sales_data = (const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}
  • 一個const成員函數(shù)如果以引用的形式返回*this指針,那么它的返回類型將是常量引用。

基于const的重載
如下,當一個成員調(diào)用另一個成員的時候,this指針在其中隱式地傳遞,當display的非常量版本調(diào)用do_display的時候,它的this指針隱式地從指向非常量的指針轉(zhuǎn)換成指向常量的指針。

#include <iostream>
#include <string>
using namespace std;

class Screen{
public:
  typedef std::string::size_type pos;
  
  Screen() = default; // 因為要寫另一個構(gòu)造函數(shù)
  Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht* wd, c) {}
  
  char get() const
  {return contents[cursor];} // 類內(nèi)部聲明定義的隱式內(nèi)聯(lián)函數(shù)
  
  inline char get(pos ht, pos wd) const; // 顯示內(nèi)聯(lián)

  Screen &set(char);
  SCreen &set(pos, pos, char);
  
  Screen &move(pos r, pos c); //能在之后被設(shè)為內(nèi)聯(lián)函數(shù)

  Screen &display(std::ostream &os)
  {do_display(os); return *this;}

  const Screen &display(std::ostream &os) const
  {do_display(os); return *this;}


private:
  pos cursor = 0;  //光標的意思
  pos height = 0, width = 0;
  std::string contents;

  void do_display(std::ostream &os) const{os << contents;}

};

inline  // 在函數(shù)的定義處指定為內(nèi)聯(lián)函數(shù)
Screen &Screen::move(pos r, pos c)
{
  pos row = r * width;
  cursor = row + c; 
  return *this;  //左值
}

char Screen::get(pos r, pos c) const
{
  pos row = r * width;
  return contents[row + c];
}

inline
Screen &Screen::set(char c)
{
  contents[cursor] = c;
  return *this;
}

inline 
Screen &Screen::set(pos r, pos col, char ch)
{
  contents[r*width +col] =ch;
  return *this;
}

int main() {
  Screen myscreen(5, 5, 'F');
  char ch =myscreen.get();
  ch = myscreen.get(0, 0);
  cout << ch << endl;
}

注:轉(zhuǎn)換成常量:指向T類型的指針或引用分別轉(zhuǎn)換成指向const T的指針或引用:

int i ;
const int & j = i; //非常量轉(zhuǎn)換成const int 的引用
const int *p = &i; //非常量的地址轉(zhuǎn)換成const的地址
  • 類的聲明
class Screen; // Screen類的聲明

前項聲明(是一種不完全類型)的使用:可以定義指向這種類型的指針或者引用,聲明(但不能定義)以不完全類型作為參數(shù)或者返回類型的函數(shù)。
必須完成類的定義,編譯器才能知道存儲數(shù)據(jù)成員需要多少空間。因為只有當類全部完成后才算被定義,因此不能有一個類的成員類型是該類自己。
但是類的名字出現(xiàn)后,聲明了該類,因此類允許包含自身類型的引用或者指針:

class Link_Screen{
  Screen window;
  Link_Screen *next;
  Link_Screen *prev;
}
  • 友元函數(shù)
    一個類指定了友元類,則友元類的成員函數(shù)可以訪問此類的所有成員。

  • 類的作用域

  • 構(gòu)造函數(shù)再談

構(gòu)造函數(shù)初始值列表的必要性:如果成員是const、引用,或者屬于某種未提供默認構(gòu)造函數(shù)的類類型,必須通過構(gòu)造函數(shù)初始值列表為這些成員提供初值。

class ConstRef{
public:
  ConstRef(int ii);
private:
  int i;
  const int c;
  int &ri;
}

ConstRef::ConstRef(int ii)
{
  i = ii; //正確
  c = ii; //錯誤 :不能給const復(fù)制
  ri = i; //錯誤 :ri沒被初始化
}

那么成員初始化的順序是:與他們在類中的定義一致。

默認實參與構(gòu)造函數(shù):可以重寫一個使用默認實參的構(gòu)造函數(shù)

class Sales_data{
public:
  //定義默認構(gòu)造函數(shù),接受一個字符串初始值
  Sales_data(std::string s = " ") bookNo(s) {}
private:
  ....
}

  • 委托構(gòu)造函數(shù):delegating constructor,委托構(gòu)造函數(shù)就是把自己的初始化全部交給其他構(gòu)造函數(shù),受委托的構(gòu)造函數(shù)初始值列表和函數(shù)體執(zhí)行后才輪到委托構(gòu)造函數(shù)。
  • 類的靜態(tài)成員:與類直接相關(guān)的成員,不包含this指針,靜態(tài)成員函數(shù)不能聲明為const的,不能再static函數(shù)體內(nèi)使用this指針。
class Account{
  public:
    void calculate() {amount += amount * interestRate;}
    static double rate() {return interestRate;}
    static void rate(double);
  private:
    std::string owner;
    double amount;
    static constexpr int period = 30;  //period是常量表達式
    static double interestRate;
    static double initRate();
}

// static關(guān)鍵字出現(xiàn)在類內(nèi)部
void Account::rate(double newRate)  
{
  interestRate = newRate;
}

由上看出,必須在內(nèi)外初始化每個靜態(tài)成員。
類內(nèi)初始化必須要求靜態(tài)成員是字面值常量類型的constexpr

  • 靜態(tài)成員與普通成員的不同:
  1. 靜態(tài)數(shù)據(jù)成員的類型可以就是她所屬的類類型;
    2.可使用靜態(tài)成員做默認實參;
class Account{
  public:
    void calculate() {amount += amount * interestRate;}
    static double rate() {return interestRate;}
    static void rate(double);
  private:
    std::string owner;
    double amount;
    static double interestRate;
    static double initRate();
}

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

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

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