【Class Members Revisited】

1、Defining a Type Member:

  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5. class Screen {
  6. public:
  7. using pos = string::size_type;
  8. /*
  9. 这就是“类型成员”,必须先定义后使用(p232)
  10. 等价声明: typedef string::size_type pos;
  11. string::size_type 一般是 unsigned int
  12. */
  13. private:
  14. pos cursor = ; // 光标的位置
  15. pos height = , width = ; // 屏幕的高和宽
  16. string contents; // 保存内容
  17. };
  18.  
  19. int main()
  20. {
  21. return ;
  22. }

2、Member Functions of class Screen。

  1. class Screen {
  2. public:
  3. using pos = string::size_type;
  4.  
  5. Screen() = default;
  6. Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
  7.  
  8. char get() const {
  9. return contents[cursor];
  10. } // implicitly inline
  11. inline char get(pos ht, pos wd) const; // explicitly inline
  12. Screen &move(pos r, pos c);
  13. private:
  14. pos cursor = ;
  15. pos height = , width = ;
  16. string contents;
  17. };

3、Making Members inline

规模小的成员函数适合被声明为inline,例如上面的构造器和其中一个get函数默认是内联的。inline的声明既可以在类的内部也可以在类的外部,当然也可以两边同时声明,不过书上建议只在类外部定义的地方声明。补充上面的代码:

  1. inline
  2. Screen &Screen::move(pos r, pos c) {
  3. pos row = r * width;
  4. cursor = row + c;
  5. return *this;
  6. }
  7.  
  8. char Screen::get(pos r, pos c) const {
  9. pos row = r * width;
  10. return contents[row+c];
  11. }

需要注意的是内联函数应当和相应的类定义在同一个头文件中。

4、Overloading Member Functions

  1. Screen myscreen;
  2. char ch = myscreen.get(); // calls Screen::get()
  3. ch = myscreen.get(,); // calls Screen::get(pos,pos)

5、mutable Data Members

极少的一种情况(例如记录const函数被调用的次数),我们希望在const成员函数中修改类的数据成员。(正常情况下是做不到的,const函数不能修改数据成员)这个时候,可以将变量声明成mutable来做到这一点。

  1. public:
  2. void some_member() const {
  3. ++access_ctr;
  4. }
  5. private:
  6. size_t access_ctr;

这种情况无法通过编译:

  1. prog1.cpp: In member function 'void Screen::some_member() const':
  2. prog1.cpp::: error: increment of member 'Screen::access_ctr' in read-only object
  3. ++access_ctr;

把access_cstr声明成mutable即可:

  1. mutable size_t access_ctr;

6、Initializers for Data Members of Class Type

  1. class Window_mgr {
  2. private:
  3. vector<Screen> screens{Screen(, , ' ')};
  4. };

类内初始值必须是等号形式或者花括号形式。

7.23 & 7.24

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <string>
  4. #include <cstring>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. class Screen {
  9. public:
  10. using pos = string::size_type;
  11. // constructors
  12. Screen() = default;
  13. Screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') {}
  14. Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
  15. // Member Functions
  16. char get() const { return contents[cursor]; }
  17. inline char get(pos ht, pos wd) const;
  18. Screen &move(pos r, pos c);
  19. private:
  20. pos cursor = ;
  21. pos height = , width = ;
  22. string contents;
  23. };
  24.  
  25. inline
  26. Screen &Screen::move(pos r, pos c) {
  27. pos row = r * width;
  28. cursor = row + c;
  29. return *this;
  30. }
  31.  
  32. char Screen::get(pos r, pos c) const {
  33. pos row = r * width;
  34. return contents[row+c];
  35. }
  36.  
  37. class Window_mgr {
  38. private:
  39. vector<Screen> screens{Screen(, , ' ')};
  40. };
  41.  
  42. int main()
  43. {
  44. Screen myscreen;
  45. char ch = myscreen.get(); // calls Screen::get()
  46. ch = myscreen.get(,); // calls Screen::get(pos,pos)
  47. return ;
  48. }

7.25

可以,Screen类并没有涉及动态内存分配,仅包含基本数据类型、string成员,拷贝、赋值、销毁的默认合成版本可以正常工作。

7.26

在原函数的类外定义加上关键字inline即可。

【Functions That Return *this】

  1. // if move returns Screen not Screen&
  2. Screen temp = myScreen.move(,); // the return value would be copied
  3. temp.set('#'); // the contents inside myScreen would be unchanged

if move returns Screen&:

  1. // move the cursor to a given position, and set that character
  2. myScreen.move(,).set('#');

1、Returning *this from a const Member Function

A const member function that returns *this as a reference should have a
return type that is a reference to const

2、Overloading Based on const

  1. class Screen {
  2. public:
  3. // display overloaded on whether the object is const or not
  4. Screen &display(std::ostream &os)
  5. { do_display(os); return *this; }
  6. const Screen &display(std::ostream &os) const
  7. { do_display(os); return *this; }
  8. private:
  9. // function to do the work of displaying a Screen
  10. void do_display(std::ostream &os) const {os <<
  11. contents;}
  12. // other members as before
  13. };

When we call display on an object, whether that object is const determines which version of display is called:

  1. Screen myScreen(,);
  2. const Screen blank(, );
  3. myScreen.set('#').display(cout); // calls non const version
  4. blank.display(cout); // calls const version

7.27

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <string>
  4. #include <cstring>
  5. #include <vector>
  6. using namespace std;
  7.  
  8. class Screen {
  9. public:
  10. using pos = string::size_type;
  11. // constructors
  12. Screen() = default;
  13. Screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') {}
  14. Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
  15. // Member Functions
  16. char get() const { return contents[cursor]; }
  17. inline char get(pos ht, pos wd) const;
  18.  
  19. Screen &move(pos r, pos c);
  20.  
  21. Screen &set(char);
  22. Screen &set(pos, pos, char);
  23.  
  24. Screen &display(ostream &os) {
  25. do_display(os); return *this;
  26. }
  27. const Screen &display(ostream &os) const {
  28. do_display(os); return *this;
  29. }
  30. private:
  31. pos cursor = ;
  32. pos height = , width = ;
  33. string contents;
  34.  
  35. void do_display(std::ostream &os) const { os << contents; }
  36. };
  37.  
  38. inline
  39. Screen &Screen::move(pos r, pos c) {
  40. pos row = r * width;
  41. cursor = row + c;
  42. return *this;
  43. }
  44.  
  45. char Screen::get(pos r, pos c) const {
  46. pos row = r * width;
  47. return contents[row+c];
  48. }
  49.  
  50. inline Screen &Screen::set(char c) {
  51. contents[cursor] = c;
  52. return *this;
  53. }
  54.  
  55. inline Screen &Screen::set(pos r, pos col, char ch) {
  56. contents[r*width + col] = ch;
  57. return *this;
  58. }
  59.  
  60. class Window_mgr {
  61. private:
  62. vector<Screen> screens{Screen(, , ' ')};
  63. };
  64.  
  65. int main()
  66. {
  67. // Screen myscreen;
  68. // char ch = myscreen.get(); // calls Screen::get()
  69. // ch = myscreen.get(0,0); // calls Screen::get(pos,pos)
  70. // return 0;
  71. // Screen myScreen(5, 3);
  72. // const Screen blank(5, 3);
  73. // myScreen.set('#').display(cout);
  74. // blank.display(cout);
  75. Screen myScreen(, , 'X');
  76. myScreen.move(,).set('#').display(cout);
  77. cout << '\n';
  78. myScreen.display(cout);
  79. cout << '\n';
  80.  
  81. return ;
  82. }
  83.  
  84. // output:
  85. // XXXXXXXXXXXXXXXXXXXX#XXXX
  86. // XXXXXXXXXXXXXXXXXXXX#XXXX

7.28

move将返回一个副本,对myScreen的后续操作不会被改变myScreen本身,而是myScrenn的副本。

7.29

  1. XXXXXXXXXXXXXXXXXXXX#XXXX
  2. XXXXXXXXXXXXXXXXXXXXXXXXX

7.30

优点:在某些情况下可以区分成员和参数,例如:this->name = name;相比于f(string name): name(name) {}可以添加一些参数检查。

缺点:多数情况下是多余的,例如:f(string nm) nm =name;....

【Class Types】

一个类的成员类型不能是该类自己。

7.31

一个典型的不得不用前置声明的例子。

  1. class Y; // forward declaration, Y is an incomplete type.
  2.  
  3. class X {
  4. Y* pointer;
  5. };
  6.  
  7. class Y {
  8. X object;
  9. };
  10.  
  11. int main()
  12. {
  13. X x;
  14. Y y;
  15. return ;
  16. }

【c++ primer, 5e】类的其他特性(卒)的更多相关文章

  1. 【c++ primer, 5e】特殊用途语言特性

    [默认实参] 1.注意点:函数的默认实参可以在函数的声明中添加,但是后续声明只能添加默认参数而不能改变先前声明的默认参数.(函数的声明通常是定义在头文件上的,多次声明同一个函数是合法的) 2.默认实参 ...

  2. 第9章 Java类的三大特性之一:继承

    1.什么是继承 子类继承父类就是对父类的扩展,继承时会自动拥有父类所拥有的处private之外的所有成员作用:增加代码复用语法格式: class 子类名 extends 父类名{…………}第9章 Ja ...

  3. (转载)OC学习篇之---类的三大特性:封装,继承,多态

    之前的一片文章介绍了OC中类的初始化方法和点语法的使用,今天来继续学习OC中的类的三大特性,我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今 ...

  4. OC基础 类的三大特性

    OC基础  类的三大特性 OC的类和JAVA一样,都有三大特性:继承,封装,多态,那么我们就来看一下OC中类的三大特性. 1.继承 继承的特点: (1)子类从父类继承了属性和方法. (2)子类独有的属 ...

  5. Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字

    Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字 一丶Java中包的机制 首先包其实就是个文件夹.作用就是管理类. Java中每次定义一个类的时候.通过Java编译之后.都会生 ...

  6. Python 类的三大特性的综合运用 案例

    # --------------------- 类的三大特性的综合运用 案例 ------------------------- # 定义三个类:小狗,小猫,人 # 小狗:姓名,年龄(默认1岁) 吃饭 ...

  7. day36 类的三大特性---封装以及Property特性

    目录 类的封装 如果真的要拿 类的property特性 setter & deleter 类属性用法 类与对象的绑定方法和非绑定方法 对象方法&类方法&静态方法 隐藏模块内的函 ...

  8. 转 OC温故:类的三大特性(封装,继承,多态)

    原文标题:OC学习篇之---类的三大特性(封装,继承,多态) 我们都知道,面向对象程序设计中的类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今天就来看一下OC中类的三大特性 ...

  9. php类知识---trait特性

    #由于php类只支持单一继承,但我们又需要使用一些类的优秀特性,因此有了trait <?php trait cpc #trait 下的方法只能用public { function trainni ...

  10. OC学习篇之---类的三大特性(封装,继承,多态)

    之前的一片文章介绍了OC中类的初始化方法和点语法的使用:http://blog.csdn.net/jiangwei0910410003/article/details/41683873,今天来继续学习 ...

随机推荐

  1. 【python】获取网页中中文内容并分词

    # -*- coding: utf-8 -*- import urllib2 import re import time import jieba url="http://www.baidu ...

  2. hadoop入门学习整理

    技术性网站 1.http://dongxicheng.org/ 2.http://www.iteblog.com/ 3.http://www.cnblogs.com/shishanyuan/p/414 ...

  3. 图像增强:直方图均衡和小波变换【matlab】

    直方图均衡:统计图像像素灰度的直方图分布.对其进行重新分配以使图像的直方图分布更加均衡. 小波变换:图像轮廓主要体现在低频部分,可以通过对低频分解系数进行增强处理,对高频分解系数进行衰减处理,达到图像 ...

  4. poj 2662(Dijkstra+记忆化)

    题目链接:http://poj.org/problem?id=2662 思路:首先路径的选择,如果B点到终点的距离比A点到终点的最短距离短,那么就从A走到B,换句话说,就是每次都是择优选择更靠近终点的 ...

  5. 直接下载jdk压缩包方式安装

    分为下面5个步骤 1.官网下载JDK 2.检查是否安装jdk,解压缩,放到指定目录 3.配置环境变量 4.设置系统默认JDK 5. 测试jdk 1.官网下载JDK      地址: http://ww ...

  6. [MongoDB]学习笔记--User管理

    1. 创建一个超级用户 use admin db.createUser( { user: "adminUserName", pwd: "userPassword" ...

  7. 第一只python爬虫

    import urllib.request response = urllib.request.urlopen("http://www.baidu.com") html = res ...

  8. (转)SPDY

    SPDY:Google开发的基于传输控制协议(TCP)的应用层协议,目前已经被用于Google Chrome浏览器中来访问Google的SSL加密服务.SPDY并不是一种用于替代HTTP的协议,而是对 ...

  9. 10分钟让你的站点也支持Markdown

    Markdown简介 Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.Markdown 的语法十分简单,常用的标记符号也不超过十个,这种相对于 ...

  10. YOLO v1论文笔记

    You Only Look Once:Unified, Real-Time Object Detection   论文链接:https://arxiv.org/abs/1506.02640 Homep ...