zoukankan      html  css  js  c++  java
  • C++ 类 超细节攻略

    C++坑了我不少的时间,这回把类算是弄得明白一些,在此记录一下。内容非常繁杂,请做好心理准备。

    我会以代码的形式来表达,并且附上一些解释。

    ① 编译器分两步处理类:

    • 编译成员的声明
    • 直到类全部可见后才编译成员函数体

    ② C++ 中class与struct的区别?

    • C++中唯一区别就是默认的访问权限,struct是public,class是private
    • C#中区别很大,详情百度

    ③ .h文件 (注意:是struct)

     1 struct Sales_data
     2 {
     3     // 定义友元函数让其可以访问类的非公有成员
     4     friend Sales_data add(const Sales_data &, const Sales_data &);
     5 
     6 public:
     7     // Sales_data() = default;
     8     // 构造函数,不能声明const
     9     // 等同于编译器自动合成的构造函数
    10     // 在(= default)在类的内部,则默认构造函数是内联的,如在类的外部,则该成员默认不是内联的
    11 
    12     Sales_data() : Sales_data("", 0, 0) {}
    13     // 委托构造函数:使用它所属的类的其他构造函数执行自己的初始化过程
    14 
    15     /* explicit 抑制构造函数的隐式转换,只允许出现的类内*/ Sales_data(const string &s) : bookNo(s) {}
    16     Sales_data(const string &s, unsigned n, double p) : bookNo(s), units_sold(n), revenue(p*n) {}
    17 
    18     string isbn() const {return bookNo;}
    19     // 等价于
    20     // string isbn(const Sales_data *const this//隐式//) {return this->bookNo;}
    21     // 意思就是this是一个指向常量的常量指针。不能修改this中的内容。
    22 
    23     Sales_data& combine (const Sales_data&);
    24 
    25 
    26 private:
    27     double avg_price() const;
    28     string bookNo;
    29     unsigned units_sold = 0;
    30     double revenue = 0.0;
    31 };

    ④ .cpp文件

     1 Sales_data& Sales_data::combine(const Sales_data &rhs)
     2 {
     3     units_sold += this->units_sold;
     4     revenue += rhs.revenue;
     5     return *this; // 返回指针引用
     6 }
     7 
     8 double Sales_data::avg_price() const
     9 {
    10     if (units_sold)
    11         return revenue / units_sold;
    12     else
    13         return 0;
    14 }
    15 
    16 Sales_data add(const Sales_data &lhs, const Sales_data &rhs)
    17 {
    18     Sales_data sum = lhs;
    19     sum.combine(rhs);
    20     return sum;
    21 }

    ⑤ main函数

     1 int main()
     2 {
     3     Sales_data total;
     4     total.isbn();
     5     // 等价于
     6     // total.isbn(&total);
     7     // 调用时候传入了total对象的地址
     8 
     9     const Sales_data sales_data;
    10     // 直到构造函数完成初始化过程,对象才能真正取得其“常量”属性
    11     // 构造函数在const对象的构造过程中可以向其写值
    12 
    13     total.combine(sales_data).isbn();
    14     // 非引用传参调用拷贝构造(此函数是引用参数,则没有拷贝构造)
    15     // 返回一个类对象调用拷贝构造
    16 
    17     total = sales_data;
    18     // 赋值操作
    19 
    20     Sales_data obj();  // 声明了一个函数
    21     Sales_data obj2;   // 声明了一个对象
    22 
    23     Sales_data item;
    24     string null_book = "9-999-99999-9";
    25     item.combine(null_book); // 将null-book隐式转换成Sales_data对象
    26     //item.combine("9-999-99999-9"); // 错误,只允许一步转换,不能将字符转换成string再转换成对象
    27 
    28     // this 是一个常量指针
    29     return 0;
    30 }

    ⑥ class Screen 与⑦的类示例友元类

     1 class Screen
     2 {
     3 public:
     4     typedef std::string::size_type pos;
     5     // 等同于
     6     // using pos = std::string::size_type;
     7     // 必须先定义后使用
     8 
     9     friend class Window_mgr;
    10     // Window_mgr的成员可以访问Screen类的私有成员
    11 
    12     // friend void Window_mgr::clear(ScreenIndex);
    13     // 让函数作为友元
    14 
    15     Screen() = default;
    16     Screen(pos ht, pos wd, char c) : height(ht), width(wd), contents(ht * wd, c) {}
    17 
    18     char get() const // 隐式内联
    19     {
    20         return contents[cursor];
    21     }
    22 
    23     inline char get(pos ht, pos wd) const; // 显式内联
    24 
    25     Screen &move(pos r, pos c); // 可以在类的外部声明时定义成内联函数
    26 
    27     Screen &set(char);
    28 
    29     Screen &set(pos, pos, char);
    30 
    31     const Screen &display() const;
    32 
    33     void dummy_fcn(pos height)
    34     {
    35         cursor = width * height; // 用的是参数height
    36         cursor = width * this->height; // 用的是成员height
    37         // cursor = width * ::height; // 用的是全局的height
    38     }
    39 
    40 private:
    41     pos cursor = 0;
    42     pos height = 0, width = 0;
    43     std::string contents;
    44     mutable size_t access_ctr = 0; // mutable(可变数据成员),在const成员函数中也可以改变值
    45 };
    46 
    47 char Screen::get(pos ht, pos wd) const
    48 {
    49     pos row = ht * width;
    50     ++access_ctr; // 正确
    51     // ++cursor; 错误
    52     return contents[row + wd];
    53 }
    54 
    55 inline Screen &Screen::move(pos r, pos c) // 声明的时候声明inline函数
    56 {
    57     pos row = r * width;
    58     cursor = row + c;
    59     return *this;
    60 }
    61 
    62 inline Screen &Screen::set(char c)
    63 {
    64     contents[cursor] = c;
    65     return *this;
    66     // 返回对象的引用,说明返回的是对象本身,而不是对象的拷贝
    67     // 如果返回类型为Screen,则返回的是对象的拷贝
    68 }
    69 
    70 inline Screen &Screen::set(pos r, pos col, char ch)
    71 {
    72     contents[r * width + col] = ch;
    73     return *this;
    74 }
    75 
    76 inline const Screen &Screen::display() const
    77 {
    78     return *this; // const成员函数返回其指针,则为常量指针
    79 }

    ⑦ class Window_mgr

     1 class Window_mgr
     2 {
     3 public:
     4     using ScreenIndex = std::vector<Screen>::size_type;
     5 
     6     void Clear(ScreenIndex);
     7 
     8     ScreenIndex addScreen(const Screen&);
     9 
    10 private:
    11     std::vector<Screen> screens{ Screen(24, 80, ' ') };
    12     // 类内初始值,必须以符号=或{}表示
    13 };
    14 
    15 void Window_mgr::Clear(ScreenIndex index) // void 为作用域之外,从Window_mgr开始为作用域内
    16 {
    17     Screen &s = screens[index];
    18     s.contents = std::string(s.height * s.width, ' ');
    19     // 因Window_mgr是Screen的友元类,所以可以访问Screen的私有成员height、width和contents
    20     // 注:友元关系不存在传递性,如果Window_mgr有友元类,其友元类没有访问Screen的权利
    21 }
    22 
    23 Window_mgr::ScreenIndex Window_mgr::addScreen(const Screen &s) // 返回类型在类作用域中定义,则必须用类名
    24 {
    25     screens.push_back(s);
    26     return screens.size() - 1;
    27 }

    如有补充欢迎留言~

  • 相关阅读:
    pcntl_fork 导致 MySQL server has gone away 解决方案
    视频网站 阻止迅雷劫持下载
    推荐大家使用的CSS书写规范、顺序
    console对象
    js Math函数
    致13级师弟师妹关于校招的一些话
    UVA514 铁轨 Rails:题解
    SP1805 HISTOGRA
    洛谷 P4363 [九省联考2018]一双木棋chess 题解
    比赛:大奔的方案solution
  • 原文地址:https://www.cnblogs.com/SHOR/p/8448080.html
Copyright © 2011-2022 走看看