一、const
1. 修饰成员函数
用const
修饰成员函数时,const
修饰 this
指针指向的内存区域,成员函数体内不可以修改本类中的任何普通成员变量,当成员变量类型符前用 mutable
修饰时例外。
int myFun(void) const {} // const 修饰的是成员函数 // 函数内不能修改
类中:
#include <iostream> class Data { private: int data; mutable int num; // 添加可修改标志 public: // 遍历 成员的函数 不会去修改成员的值 void myPrintData() const { std::cout << this->data << std::endl; // data = 1; // 错误 , const 不能修改 num = 200; } public: Data() { std::cout << "无参构造" << std::endl; } Data(int data) { this->data = data; std::cout << "有参构造" << std::endl; } Data(const Data &ob) { this->data = ob.data; std::cout << "拷贝构造" << std::endl; } ~Data() { std::cout << "析构函数" << std::endl; } }; int main() { Data ob1(100); ob1.myPrintData(); return 0; }
2. 修饰对象称为常对象
const int num = 10;
不会开辟空间,num
会被放入符号表中。
int main() { // 常对象 const Data ob1(200); // 常对象只能调用const修饰的函数,遍历成员数据 ob1.myPrintData(); // 访问没有const修饰的函数是不允许的 return 0; }
二、友元函数
c++允许友元访问私有数据。
1. 语法:
friend
关键字只出现在声明处 其他类、类成员函数、全局函数都可声明为友元 友元函数
不是类的成员,不带this
指针 友元函数可访问对象任意成员属性,包括私有属性。
2. 普通全局函数作为类的友元
#include <iostream> class Room { private: friend void goodGayVisit(Room &room); // 将goodGayVisit作为类的友元函数 // 可以访问类中的所有数据 但是 不是 类的成员 private: std::string bedRoom; //卧室 public: std::string sittingRoom; // 客厅 public: Room(): bedRoom("卧室"), sittingRoom("客厅") { } }; // 友元函数在类外定义,且非对象的函数,没有this指针 void goodGayVisit(Room &room) { std::cout << "访问" << room.sittingRoom << std::endl; std::cout << "访问" << room.bedRoom << std::endl; // 可以访问私有属性 } int main() { Room myRoom; goodGayVisit(myRoom); return 0; }
3. 类作为另一个类的友元
- 类的某个成员函数作为另一个类的友元
- 类整体作为另一个类的友元
这里碰到一个问题,如果分文件写,会造成循环依赖的问题。
在设计类的时候要充分考虑头文件引入的问题,尽量避免多次引入相同的头文件,以及相互引入(相互会出现错误)。
4. 一个电视机类
封装电视机和遥控器类:
#include <iostream> using namespace std; class TV { private: // 添加一个遥控器 friend class Remote; private: enum { ON, OFF }; enum { minVol, maxVol=100 }; enum { minChannel=1, maxChannel=255 }; private: int state; // 电视状态,开机/关机 int volume; // 电视机音量 int channel; // 电视频道 public: // 构造函数 TV(): state(OFF), volume(minVol), channel(minChannel) {} ~TV() {}; public: // 开关 void switchButton() { state = state == ON ? OFF : ON; } // 音量 // 音量+ void volumeUp() { if (volume >= maxVol) { return ; } ++volume; } // 音量- void volumeDown() { if (volume <= minVol) { return ; } --volume; } // 频道 // 频道+ void channelUp() { if (channel >= maxChannel) { return ; } ++channel; } // 频道- void channelDown() { if (channel <= minChannel) { return ; } --channel; } // 显示电视机状态 std::string whatState() { return state == ON ? "开机" : "关机"; } // 显示音量 int whatVolume() { return volume; } // 显示频道 int whatChannel() { return channel; } // 显示所有状态 void showTVState() { std::cout << "电视机状态: " << whatState() << std::endl; std::cout << "电视机音量: " << whatVolume() << std::endl; std::cout << "电视机频道: " << whatChannel() << std::endl; } }; // Remote 类 遥控器 /** 该类作为TV的友元类 */ class Remote { private: TV *tv; public: Remote(TV *pTv): tv(pTv) {} public: // 音量 // 音量+ void volumeUp() { tv->volumeUp(); } // 音量- void volumeDown() { tv->volumeDown(); } // 频道 // 频道+ void channelUp() { tv->channelUp(); } // 频道- void channelDown() { tv->channelDown(); } // 电视开关 void switchButton() { tv->switchButton(); } // 设置频道 void setChannel(int num) { // 频道是否有效 if (num >= TV::minChannel && num <= TV::maxChannel) { tv->channel = num; } } void showTVState() { tv->showTVState(); } }; // 测试1 void test01() { TV tv; tv.switchButton(); // 开机 tv.volumeDown(); // 0 tv.volumeUp(); // 1 tv.volumeUp(); // 2 tv.volumeUp(); // 3 tv.volumeDown(); //2 tv.channelDown(); // 1 tv.channelDown(); // 1 tv.channelUp(); // 2 tv.channelUp(); //3 tv.showTVState(); } // 测试2 void test02() { TV tv; Remote remote(&tv); remote.switchButton(); // 开机 remote.volumeDown(); // 0 remote.volumeUp(); // 1 remote.volumeUp(); // 2 remote.volumeUp(); // 3 remote.volumeDown(); //2 remote.channelDown(); // 1 remote.channelDown(); // 1 remote.channelUp(); // 2 remote.channelUp(); //3 remote.showTVState(); remote.setChannel(22); remote.showTVState(); } int main() { test01(); test02(); return 0; }
关于枚举:
枚举是一个常量,在编译的时候会放入常量区,可以直接使用类名:枚举变量
调用。