C++步步为营

C++---CHAPTER 7: CLASS

2019-07-22  本文已影响0人  世界上的一道风
std::string isbn() const {return bookNo;}
Sales_data& Sales_data::combine(const Sales_data &rhs)
{
  units_sold += rhs.units_sold;
  revenue += rhs.revenue;
  return *this;  //解引用指针获取执行该函数的对象。
}
Sales_data = (const std::string &s, unsigned n, double p): bookNo(s), units_sold(n), revenue(p*n) {}

基于const的重载
如下,当一个成员调用另一个成员的时候,this指针在其中隐式地传递,当display的非常量版本调用do_display的时候,它的this指针隐式地从指向非常量的指针转换成指向常量的指针。

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

class Screen{
public:
  typedef std::string::size_type pos;
  
  Screen() = default; // 因为要写另一个构造函数
  Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht* wd, c) {}
  
  char get() const
  {return contents[cursor];} // 类内部声明定义的隐式内联函数
  
  inline char get(pos ht, pos wd) const; // 显示内联

  Screen &set(char);
  SCreen &set(pos, pos, char);
  
  Screen &move(pos r, pos c); //能在之后被设为内联函数

  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  // 在函数的定义处指定为内联函数
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;
}

注:转换成常量:指向T类型的指针或引用分别转换成指向const T的指针或引用:

int i ;
const int & j = i; //非常量转换成const int 的引用
const int *p = &i; //非常量的地址转换成const的地址
class Screen; // Screen类的声明

前项声明(是一种不完全类型)的使用:可以定义指向这种类型的指针或者引用,声明(但不能定义)以不完全类型作为参数或者返回类型的函数。
必须完成类的定义,编译器才能知道存储数据成员需要多少空间。因为只有当类全部完成后才算被定义,因此不能有一个类的成员类型是该类自己。
但是类的名字出现后,声明了该类,因此类允许包含自身类型的引用或者指针:

class Link_Screen{
  Screen window;
  Link_Screen *next;
  Link_Screen *prev;
}

构造函数初始值列表的必要性:如果成员是const、引用,或者属于某种未提供默认构造函数的类类型,必须通过构造函数初始值列表为这些成员提供初值。

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

ConstRef::ConstRef(int ii)
{
  i = ii; //正确
  c = ii; //错误 :不能给const复制
  ri = i; //错误 :ri没被初始化
}

那么成员初始化的顺序是:与他们在类中的定义一致。

默认实参与构造函数:可以重写一个使用默认实参的构造函数

class Sales_data{
public:
  //定义默认构造函数,接受一个字符串初始值
  Sales_data(std::string s = " ") bookNo(s) {}
private:
  ....
}

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关键字出现在类内部
void Account::rate(double newRate)  
{
  interestRate = newRate;
}

由上看出,必须在内外初始化每个静态成员。
类内初始化必须要求静态成员是字面值常量类型的constexpr

  1. 静态数据成员的类型可以就是她所属的类类型;
    2.可使用静态成员做默认实参;
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;
}
上一篇 下一篇

猜你喜欢

热点阅读