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 }

如有补充欢迎留言~

posted @ 2018-02-14 11:26  Sooda  阅读(455)  评论(0编辑  收藏  举报