一、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. 类作为另一个类的友元

  1. 类的某个成员函数作为另一个类的友元
  2. 类整体作为另一个类的友元

这里碰到一个问题,如果分文件写,会造成循环依赖的问题。

在设计类的时候要充分考虑头文件引入的问题,尽量避免多次引入相同的头文件,以及相互引入(相互会出现错误)。

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;
}

关于枚举:

枚举是一个常量,在编译的时候会放入常量区,可以直接使用类名:枚举变量调用。