[C++] 友元的初始

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

关于枚举:

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

全部评论

相关推荐

04-11 00:51
已编辑
门头沟学院 Java
先说一下楼主的情况:双非本大三,两段实习,javaer,想要找一个暑期大厂offer,努力了两个月,三月份每天的状态就是算法,八股,项目,四月份更是一个面试没有,最终还是没有结果,心碎了一地。期间面了一些中小厂,大厂只有腾讯约面,其他大厂都投了一遍,但是还是石沉大海。再看一下楼主的面试结果吧,就不说ttl了腾讯s3:三面挂csig:一面挂teg:三面挂wxg:一面挂没错,面了八次腾讯,两次三面挂,当时真的心都碎了。其他中小厂都有面,有的没过,有的oc,但是都没有去。其他大厂投了简历,但是不是简历挂,就是测评挂,都说今年行情好很多,各大厂都扩招,可是问题出在那里呢?学历背景吗?实习经历吗?还是简历不够好看?依稀记得,从年初七就离开了家里,回到学校,早早准备面试,当时自己认为凭借着自己的两段实习经历,以及大二就开始准备的八股算法,拿大厂offer不是问题,但是还是不敢放松,回校的状态每天就是算法,八股,还有查看各种招聘信息,想着尽早投机会多,但是事实证明,投的早,不如投的刚刚好。当时想着,先投一些中小厂开始面试,找找面试感觉,从2.10就开始有面试了,基本都是线下面试,面试的感觉都很不错,觉得自己的状态慢慢回来了,期间也有oc一些中小厂,但是自己的目标并不在此,只是想练一下手,遂拒。后面投了腾讯的暑期实习基地,不久就约面了,第一次面这么大的厂,多少有点紧张,好在运气还不错,遇到的面试官也比较好,一直干到了三面,期间看牛客有不少说一面就挂了的,感觉自己还是比较幸运的,但是没想到倒在了三面,一周后就挂了,伤心是有的,但是想到这才刚刚开始,还有很多机会,便继续准备下一次面试了,很快,被另外一个部门捞了,一进会议,面试官没开摄像头,看网上说没开摄像头很多都是kpi,但是自己给自己打气,认为面试官只是不方便开摄像头罢了,面完,感觉良好,没问什么很难得问题,基本都答出来了,算法两道也a了一道,感觉实习不会这么严格吧?还是过了一会挂了,因为这个?还是技术不太匹配?面试过程中说搞C++的,心想,搞c++的你面我干啥?唉,这时候有点气馁,然后就接下来半个月没有面试。这时已经是三月底了,看到牛客好多人都已经陆陆续续拿到了offer,看人家的面试准备也没那么早,有0实习的,有没刷算法的,有两个面的,,,唉,反正是一言难尽啊,感觉努力没有什么意义,面试多半是看面试官的感觉,主观性很大啊,只要你技术没有太大的问题。第三次面试腾讯,面试来的比较突然,期间已经有几天没看八股什么的了,临时看了一下之前自己做的面试笔记,但是面试却异常顺利,三天闯到了三面,自己也不敢相信,三面玩感觉也良好,脑子里不得不想着一些“offer结算画面”,但是过了一会查看流程显示“流程终止”,我?哎,当时真的有苦说不出啊,也是一晚没睡。后面就逐渐开始褪去大厂梦了,看着曾经跟自己交流的牛油,朋友,认识的人,觉得他们技术不太如你,算法刷的没你多,进了大厂,但是这又如何呢?能力强不强不是你了说了,面试官说了算。也逐渐知道,不是你能力好就可以了,还得有运气,运气,运气。这个过程太累了,和自己和解吧,不用非得大厂,找个合适一点的就好,放轻松一点。今天有点心事睡不着,闲着想写一些自己的面试过程,勿喷。附上一张面试的情况,公司就不方便透露了。
怒卷的斯科特:八分运气两分实力
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务