【c++ primer, 5e】类的其他特性(卒)
【Class Members Revisited】
1、Defining a Type Member:
- #include <iostream>
- #include <string>
- using namespace std;
- class Screen {
- public:
- using pos = string::size_type;
- /*
- 这就是“类型成员”,必须先定义后使用(p232)
- 等价声明: typedef string::size_type pos;
- string::size_type 一般是 unsigned int
- */
- private:
- pos cursor = ; // 光标的位置
- pos height = , width = ; // 屏幕的高和宽
- string contents; // 保存内容
- };
- int main()
- {
- return ;
- }
2、Member Functions of class Screen。
- class Screen {
- public:
- using pos = string::size_type;
- Screen() = default;
- Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
- char get() const {
- return contents[cursor];
- } // implicitly inline
- inline char get(pos ht, pos wd) const; // explicitly inline
- Screen &move(pos r, pos c);
- private:
- pos cursor = ;
- pos height = , width = ;
- string contents;
- };
3、Making Members inline
规模小的成员函数适合被声明为inline,例如上面的构造器和其中一个get函数默认是内联的。inline的声明既可以在类的内部也可以在类的外部,当然也可以两边同时声明,不过书上建议只在类外部定义的地方声明。补充上面的代码:
- 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];
- }
需要注意的是内联函数应当和相应的类定义在同一个头文件中。
4、Overloading Member Functions
- Screen myscreen;
- char ch = myscreen.get(); // calls Screen::get()
- ch = myscreen.get(,); // calls Screen::get(pos,pos)
5、mutable Data Members
极少的一种情况(例如记录const函数被调用的次数),我们希望在const成员函数中修改类的数据成员。(正常情况下是做不到的,const函数不能修改数据成员)这个时候,可以将变量声明成mutable来做到这一点。
- public:
- void some_member() const {
- ++access_ctr;
- }
- private:
- size_t access_ctr;
这种情况无法通过编译:
- prog1.cpp: In member function 'void Screen::some_member() const':
- prog1.cpp::: error: increment of member 'Screen::access_ctr' in read-only object
- ++access_ctr;
把access_cstr声明成mutable即可:
- mutable size_t access_ctr;
6、Initializers for Data Members of Class Type
- class Window_mgr {
- private:
- vector<Screen> screens{Screen(, , ' ')};
- };
类内初始值必须是等号形式或者花括号形式。
7.23 & 7.24
- #include <cstdio>
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <vector>
- using namespace std;
- class Screen {
- public:
- using pos = string::size_type;
- // constructors
- Screen() = default;
- Screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') {}
- Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
- // Member Functions
- char get() const { return contents[cursor]; }
- inline char get(pos ht, pos wd) const;
- Screen &move(pos r, pos c);
- private:
- pos cursor = ;
- pos height = , width = ;
- string 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];
- }
- class Window_mgr {
- private:
- vector<Screen> screens{Screen(, , ' ')};
- };
- int main()
- {
- Screen myscreen;
- char ch = myscreen.get(); // calls Screen::get()
- ch = myscreen.get(,); // calls Screen::get(pos,pos)
- return ;
- }
7.25
可以,Screen类并没有涉及动态内存分配,仅包含基本数据类型、string成员,拷贝、赋值、销毁的默认合成版本可以正常工作。
7.26
在原函数的类外定义加上关键字inline即可。
【Functions That Return *this】
- // if move returns Screen not Screen&
- Screen temp = myScreen.move(,); // the return value would be copied
- temp.set('#'); // the contents inside myScreen would be unchanged
if move returns Screen&:
- // move the cursor to a given position, and set that character
- 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
- class Screen {
- public:
- // display overloaded on whether the object is const or not
- Screen &display(std::ostream &os)
- { do_display(os); return *this; }
- const Screen &display(std::ostream &os) const
- { do_display(os); return *this; }
- private:
- // function to do the work of displaying a Screen
- void do_display(std::ostream &os) const {os <<
- contents;}
- // other members as before
- };
When we call display on an object, whether that object is const determines which version of display is called:
- Screen myScreen(,);
- const Screen blank(, );
- myScreen.set('#').display(cout); // calls non const version
- blank.display(cout); // calls const version
7.27
- #include <cstdio>
- #include <iostream>
- #include <string>
- #include <cstring>
- #include <vector>
- using namespace std;
- class Screen {
- public:
- using pos = string::size_type;
- // constructors
- Screen() = default;
- Screen(pos ht, pos wd): height(ht), width(wd), contents(ht * wd, ' ') {}
- Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht * wd, c) {}
- // Member Functions
- char get() const { return contents[cursor]; }
- inline char get(pos ht, pos wd) const;
- Screen &move(pos r, pos c);
- Screen &set(char);
- Screen &set(pos, pos, char);
- Screen &display(ostream &os) {
- do_display(os); return *this;
- }
- const Screen &display(ostream &os) const {
- do_display(os); return *this;
- }
- private:
- pos cursor = ;
- pos height = , width = ;
- 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;
- }
- class Window_mgr {
- private:
- vector<Screen> screens{Screen(, , ' ')};
- };
- int main()
- {
- // Screen myscreen;
- // char ch = myscreen.get(); // calls Screen::get()
- // ch = myscreen.get(0,0); // calls Screen::get(pos,pos)
- // return 0;
- // Screen myScreen(5, 3);
- // const Screen blank(5, 3);
- // myScreen.set('#').display(cout);
- // blank.display(cout);
- Screen myScreen(, , 'X');
- myScreen.move(,).set('#').display(cout);
- cout << '\n';
- myScreen.display(cout);
- cout << '\n';
- return ;
- }
- // output:
- // XXXXXXXXXXXXXXXXXXXX#XXXX
- // XXXXXXXXXXXXXXXXXXXX#XXXX
7.28
move将返回一个副本,对myScreen的后续操作不会被改变myScreen本身,而是myScrenn的副本。
7.29
- XXXXXXXXXXXXXXXXXXXX#XXXX
- XXXXXXXXXXXXXXXXXXXXXXXXX
7.30
优点:在某些情况下可以区分成员和参数,例如:this->name = name;相比于f(string name): name(name) {}可以添加一些参数检查。
缺点:多数情况下是多余的,例如:f(string nm) nm =name;....
【Class Types】
一个类的成员类型不能是该类自己。
7.31
一个典型的不得不用前置声明的例子。
- class Y; // forward declaration, Y is an incomplete type.
- class X {
- Y* pointer;
- };
- class Y {
- X object;
- };
- int main()
- {
- X x;
- Y y;
- return ;
- }
【c++ primer, 5e】类的其他特性(卒)的更多相关文章
- 【c++ primer, 5e】特殊用途语言特性
[默认实参] 1.注意点:函数的默认实参可以在函数的声明中添加,但是后续声明只能添加默认参数而不能改变先前声明的默认参数.(函数的声明通常是定义在头文件上的,多次声明同一个函数是合法的) 2.默认实参 ...
- 第9章 Java类的三大特性之一:继承
1.什么是继承 子类继承父类就是对父类的扩展,继承时会自动拥有父类所拥有的处private之外的所有成员作用:增加代码复用语法格式: class 子类名 extends 父类名{…………}第9章 Ja ...
- (转载)OC学习篇之---类的三大特性:封装,继承,多态
之前的一片文章介绍了OC中类的初始化方法和点语法的使用,今天来继续学习OC中的类的三大特性,我们在学习Java的时候都知道,类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今 ...
- OC基础 类的三大特性
OC基础 类的三大特性 OC的类和JAVA一样,都有三大特性:继承,封装,多态,那么我们就来看一下OC中类的三大特性. 1.继承 继承的特点: (1)子类从父类继承了属性和方法. (2)子类独有的属 ...
- Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字
Java开发知识之Java类的高级特性,内部类.以及包使用.跟常量关键字 一丶Java中包的机制 首先包其实就是个文件夹.作用就是管理类. Java中每次定义一个类的时候.通过Java编译之后.都会生 ...
- Python 类的三大特性的综合运用 案例
# --------------------- 类的三大特性的综合运用 案例 ------------------------- # 定义三个类:小狗,小猫,人 # 小狗:姓名,年龄(默认1岁) 吃饭 ...
- day36 类的三大特性---封装以及Property特性
目录 类的封装 如果真的要拿 类的property特性 setter & deleter 类属性用法 类与对象的绑定方法和非绑定方法 对象方法&类方法&静态方法 隐藏模块内的函 ...
- 转 OC温故:类的三大特性(封装,继承,多态)
原文标题:OC学习篇之---类的三大特性(封装,继承,多态) 我们都知道,面向对象程序设计中的类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今天就来看一下OC中类的三大特性 ...
- php类知识---trait特性
#由于php类只支持单一继承,但我们又需要使用一些类的优秀特性,因此有了trait <?php trait cpc #trait 下的方法只能用public { function trainni ...
- OC学习篇之---类的三大特性(封装,继承,多态)
之前的一片文章介绍了OC中类的初始化方法和点语法的使用:http://blog.csdn.net/jiangwei0910410003/article/details/41683873,今天来继续学习 ...
随机推荐
- 【python】获取网页中中文内容并分词
# -*- coding: utf-8 -*- import urllib2 import re import time import jieba url="http://www.baidu ...
- hadoop入门学习整理
技术性网站 1.http://dongxicheng.org/ 2.http://www.iteblog.com/ 3.http://www.cnblogs.com/shishanyuan/p/414 ...
- 图像增强:直方图均衡和小波变换【matlab】
直方图均衡:统计图像像素灰度的直方图分布.对其进行重新分配以使图像的直方图分布更加均衡. 小波变换:图像轮廓主要体现在低频部分,可以通过对低频分解系数进行增强处理,对高频分解系数进行衰减处理,达到图像 ...
- poj 2662(Dijkstra+记忆化)
题目链接:http://poj.org/problem?id=2662 思路:首先路径的选择,如果B点到终点的距离比A点到终点的最短距离短,那么就从A走到B,换句话说,就是每次都是择优选择更靠近终点的 ...
- 直接下载jdk压缩包方式安装
分为下面5个步骤 1.官网下载JDK 2.检查是否安装jdk,解压缩,放到指定目录 3.配置环境变量 4.设置系统默认JDK 5. 测试jdk 1.官网下载JDK 地址: http://ww ...
- [MongoDB]学习笔记--User管理
1. 创建一个超级用户 use admin db.createUser( { user: "adminUserName", pwd: "userPassword" ...
- 第一只python爬虫
import urllib.request response = urllib.request.urlopen("http://www.baidu.com") html = res ...
- (转)SPDY
SPDY:Google开发的基于传输控制协议(TCP)的应用层协议,目前已经被用于Google Chrome浏览器中来访问Google的SSL加密服务.SPDY并不是一种用于替代HTTP的协议,而是对 ...
- 10分钟让你的站点也支持Markdown
Markdown简介 Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.Markdown 的语法十分简单,常用的标记符号也不超过十个,这种相对于 ...
- YOLO v1论文笔记
You Only Look Once:Unified, Real-Time Object Detection 论文链接:https://arxiv.org/abs/1506.02640 Homep ...