【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】类的其他特性(卒)的更多相关文章

  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. [ppurl]从”皮皮书屋”下载电子书的姿势

    (欢迎转载,转载请注明出处:http://blog.csdn.net/hcbbt/article/details/42072545) 写在前面的扯皮 为什么标题的"皮皮书屋"加上了 ...

  2. Ubuntu14.4下搭配WEB服务器(apache + php + mysql)

    今天,趁着自己动手安装web服务器的余热,将Ubuntu14.4搭配WEB服务器的过程记录下来. “一切皆文件”. 说明:网上关于类似搭配web服务器的教程,案例不计其数,但自己亲自动手“试试”,一定 ...

  3. 【VBA】合并多个excel文件

    From http://www.zhihu.com/question/20366713 VBA代码如下: Sub 工作薄间工作表合并() Dim FileOpen Dim X As Integer A ...

  4. ORB特征提取与匹配

    ORB特征是目前最优秀的特征提取与匹配算法之一,下面具体讲解一下: 特征点的检测 图像的特征点可以简单的理解为图像中比较显著显著的点,如轮廓点,较暗区域中的亮点,较亮区域中的暗点等.ORB采用FAST ...

  5. 基于字典SR各种方法【稀疏编码多种方法】

    基于字典的图像超分辨率实现 - CSDN博客 http://blog.csdn.net/u011630458/article/details/65635155 简介 这段时间在看基于字典的单帧图像超分 ...

  6. poj 2914(stoer_wanger算法求全局最小割)

    题目链接:http://poj.org/problem?id=2914 思路:算法基于这样一个定理:对于任意s, t   V ∈ ,全局最小割或者等于原图的s-t 最小割,或者等于将原图进行 Cont ...

  7. Django之前端模板继承

    在使用Django进行web开发时,往往会构造一个基础框架模板即base.html,而后在其子模板中对它所包含站点公用部分和定义块进行重载. 首先创建一个base.html,源码为: <!DOC ...

  8. 阿里面试经历JAVA总结

    为记录阿里的电面经历,特与大家分享,岗位是JAVA研发工程师. 一面主要问题如下: 1)首先自我介绍 2)数据结构算法的基本问题,如排序算法,二叉树遍历,后序遍历非递归,图的最短路径问题 3)对一个数 ...

  9. 俄罗斯方块——shell

    #!/bin/bash # Tetris Game # xhchen<[email]xhchen@winbond.com.tw[/email]> #APP declaration APP_ ...

  10. CF679C(Bear and Square Grid) 经典好题

    题目链接:传送门 题目大意:给你一个n*n包含".","X"的图,你有一次机会选择一个k*k的子矩阵,将子矩阵全部变为".",问当操作过后, ...