#include <stdio.h>
#include<iostream>
#include <string.h>
#include <stdlib.h>
#include<string>
#include<vector>
using namespace std;
//
class Screen {
public:
typedef string::size_type pos; //专门用来定义类型 的成员必须先定义后使用他
/*
screen 的用户不会知道screen内部使用了一个string对象来存放他的数据,
通过把pos定义成public成员可以隐藏screen的实现细节
*/
Screen() = default;
Screen(int a,int b){}
Screen(pos ht, pos wd, char c) :height(ht), width(wd), contents(ht*wd, c){ }
char get() const { //隐式的内联,const写到后面,这是个常成员函数
/*
常成员函数意义:不改变对象的成员变量的值,与普通的成员函数改变变量值形成对比
*/
//height = 1; //编译报错,常成员函数不可以修改成员变量的值哦!
return contents[cursor];
}
inline char get(pos ht, pos wd)const; //显式的内联,也是常成员函数
Screen &move(pos r, pos c); //能在之后类的外部被设为内联
const Screen& display(ostream &os); //const成员,返回const 型的Screen对象 ,即,常量对象,常量对象的成员一般是不能修改的
Screen& display_2(ostream&os) {
do_display(os);
return *this;
}
const Screen &display(ostream&os) const{
do_display(os);
return *this;
}
private:
pos cursor = 0;
pos height = 0, width = 0;
string contents;
void do_display(ostream&os)const {
os << contents;
}
public:
//可变数据成员
/*
有时候希望改变类的某个数据成员,即使他是在一个const成员函数里面
那么可以通过在变量的声明中加入mutable关键字做到
一个可变数据成员(mutable data member)永远不会是const,即使他是const对象的成员
*/
void some_member() const; // 声明一个常类成员函数,那么他就不能修改类的成员数据,除非是mutable
private:
mutable size_t access_ctr;// 既使一个在const对象内也能被修改
public: //很一般的成员函数
Screen& set(char);
Screen &set(pos, pos, char);
};
//令move成员作为内联函数
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];
}
//返回*this的成员函数
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;
}
//const成员函数,而且返回引用
inline const Screen& Screen::display(ostream&a) {
//height = 1;//因为不是常成员函数,所以可以修改成员变量
//一个const成员函数如果以引用的形式返回*this,那么他的返回类型是常量引用
//++access_ctr;//因为是mutable类型,所以可以修改哦
return *this;
}
//重载成员函数
Screen myscreen;
char ch = myscreen.get(); //调用Screen::get()
char ch2 = myscreen.get(0, 0); //调用Screen::get(0,0)
void Screen::some_member() const{
// 这里你换成了height成员数据,那他就报错说不能修改
++access_ctr;//保存一个计数值,用于记录成员函数被调用的次数
}
class window_mgr {
private:
//这个window_mgr追踪的Screen
//默认情况下,一个window_mgr包含一个标准尺度的空白Screen
vector<Screen> screens{ Screen(24,80, ' ') };//容器screens包含一个Screen对象
};
/*
当我们初始化 类类型 的成员时,需要为构造函数传递一个符合成员类型的实参数
*/
int main() {
cout << "7.3 类的其他属性";
Screen myScreen; //非常量的对象
//display是一个返回常量引用,调用set会引发错误
//myScreen.display(cout).set('a');//报错!!常量引用调用非常量的成员函数,那么这个成员函数很有可能修改被调用对象的成员数据,而这与const矛盾
myScreen.display(cout).get();//返回常量对象的引用,这个常量引用调用常成员函数是OK的
myscreen.move(4, 0).set('a');
const Screen blank(5, 3);
blank.display(cout);//常量对象调用常成员,
//blank.display_2(cout);报错
return 0;
}
C++常量对象,常成员函数
最新推荐文章于 2024-07-26 15:15:48 发布