【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. VS2013远程调试IIS中的网站

    问题描述一般网站发布到远程iis中了.我们就无法调试了... 今天查到个可以远程调试iis或winform的方法: 记录下 第一步:copy 本地 C:\Program Files (x86)\Mic ...

  2. APP接口基础学习一

    PHP面向对象思想 1.客户端发送http请求到达服务器 2.服务器做出响应返回数据(XML,JSON或者其他)到达客户端 XML与JSON 的区别 1.可读性:xml胜出 2.生成数据:json胜出 ...

  3. PHP第三方登录

    参考视屏:http://www.imooc.com/learn/596 php第三方登录-QQ登录OAuth协议基本原理QQ登录前置条件以及开放平台账号申请1,一个QQ号2,一个公网通过域名可访问的w ...

  4. boost - 正则表达式xpressive

     正则表达式是一套处理文本强有力的工具: 它使用一套复杂的语法规则,可以解决文本处理领域的绝大多数问题; 而这些问题通常是字符串算法很难甚至无法解决的. C++98标准中没有内置的正则表达式支持,使得 ...

  5. 12 个免费在线的 Web 网站性能测试工具

    https://www.oschina.net/news/21033/12-free-online-tools-for-website-testing

  6. 把本地的jar包安装到maven库中

    mvn install:install-file -Dfile=E:\temp\catV1\cat-client\trunk\CAT_v1.1.1\cat-consumer\target\cat-co ...

  7. Docker入门与应用系列(五)Dockerfile

    Dockerfile是为快速构建docker image而设计的,当你使用dockerbuild 命令的时候,docker 会读取当前目录下的命名为Dockerfile(首字母大写)的纯文本文件并执行 ...

  8. 数据库设计——E-R图

    一,复习下基础 1.弱实体 这样的实体须要依赖还有一个实体.若还有一个实体不存在了.它也随之消失.相对而言,它依赖的那个实体成为强实体. 2,特殊化 在数据库设计的过程中,我们会发现.一个实体能够依照 ...

  9. mysql_表内容_操作

    1.增 语法:insert into 表 (列名,列名...) values (值,值...) # 插入单条数据 insert into 表 (列名,列名...) values (值,值...) # ...

  10. MVC4 WebAPI中如何返回一张图片

    public HttpResponseMessage Get(string imageName, int width, int height) { Image img = GetImage(image ...