来继续探索一些类的其他特征
这一章会出现,类型成员,内联函数 ,可变数据成员,重载,返回this的成员函数,基于const的重载。
还是老样子,先贴代码
Screen.h
#pragma once
#include<iostream>
using namespace std;
class Screen
{
public:
typedef size_t pos; //类型成员
typedef char con; //类型成员
Screen() = default;//要求编译器生成默认的构造函数
Screen(pos ht, pos wd) :width(wd), hight(ht), contents(ht* wd, ' ') {};
Screen(pos ht, pos wd, char c) :width(wd), hight(ht), contents(ht* wd, c) {}
char get() const //隐式内联
{
++access_ctr;
return contents[cursor];
}
char get(pos row, pos col) const;
pos get_ctr() //隐式内联
{
return access_ctr;
}
Screen& set(char c)
{
contents[cursor] = c;
return *this;
}
Screen& set(pos row, pos col, char c)
{
contents[row * width + col] = c;
return *this;
}
Screen& move(pos row, pos col);
Screen& display(ostream&);
const Screen& display(ostream&) const;
private:
void do_display(ostream&) const;
mutable pos access_ctr = 0;
pos cursor = 0;//光标当前位置
pos width = 0, hight = 0;
string contents;
};
Screen.cpp
#include<iostream>
#include"Screen.h"
using namespace std;
char Screen::get(pos row,pos col) const
{
access_ctr++;
pos result = row * width + col;
return contents[result];
}
Screen& Screen::move(pos row, pos col)
{
//access_ctr++;
pos re = row * width + col;
cursor += re;
return *this;
}
Screen& Screen::display(ostream& out)
{
do_display(out);
return *this;
}
const Screen& Screen::display(ostream& out) const
{
do_display(out);
return *this;
}
void Screen::do_display(ostream& out) const
{
out << contents;
}
run_MyScreen.cpp
#include<iostream>
#include"Screen.h"
using namespace std;
int main()
{
Screen myScreen(5, 5, 'c');
myScreen.move(4, 0).set('#').display(cout);
cout << endl;
myScreen.display(cout);
cout << endl;
Screen::con c = myScreen.get();
cout << c << endl;
Screen::pos count = myScreen.get_ctr();
cout << count;
}
来,下面开讲了。
1. 先说类型成员:在Screen.h中,public下面定义的第一个东西就是一个类型成员。类型成员与类的其他东西一样也是具有访问限制的。 我们把它定义为public,这样用户就能直接访问它了。这样,用户在使用我们的类的时候,只知道我们返回的是con和pos类型,但这个con和pos类型具体是什么类型?用户不知道。这样就隐藏了类的实现。(我是这么理解的,不知道对不对,如果不对请大佬指正,谢谢)。还需要注意一点,类型成员是先声明后使用 ,因此,通常我们都把他放到最前面。
2. 再往下走,那几个构造函数就不多赘述。
3. 再往下的get函数就内联了。内联函数是干什么的?内联函数的作用是避免函数调用的开销。它将函数在调用点内联的展开。内联机制通常用于规模小,流程直接,频繁调用的函数。 那为什么get是内联的?也没看到inline关键字啊! 原来定义在类内部的成员函数自动inline,所以它是内联的。其他不定义在类内部的,通常在定义出声明inline。
4. 再下面又出现一个get函数,这就是重载,这个应该都懂,这两个get的形参不一样,所以发生了重载。
5. 看下面私有数据成员里面有一个 mutable pos access_ctr = 0; mutable是干什么的?它是可变数据成员 如果我们希望在一个const成员函数中修改调用对象的值,那我们可以把这个值声明称mutable。比如上上面程序中,记录函数被调用次数。
6. 观察一下我们的set函数以及move函数。它们返回的都是对象的引用。这样有什么好处?返回引用的函数是左值的,意味着这些函数返回的是对象本身而不是对象的副本!! 这样的话,在我们的主函数里执行这个:myScreen.move(4, 0).set(’#’).display(cout)。是真正改变的myScreen对象,而不是它的副本。假如我们的move函数返回的不是引用,那它返回的就是myScreen的副本,然后set改变的就是它的副本。
7. 基于const的重载。你会发现我们定义了两个display,它们只差一个const。这两个display是重载的。能不能只定义一个不带const的display?不行,常量对象不能调用非常量函数 能不能只定义一个带const的?可以,不过,好像非常量版本才是更好的匹配。所以我们就定义了两个。同时,我们又定义了一个do_display,这样既保证调用display的时候不会改变contents的内容,又既可以通过非常量对象还可以通过常量对象调用。