C++ Primer第七章③

C++ Primer

第七章 类

类的其他特性

前面通过Sales_data类我们已经了解了很多类的知识了,但是作为C++这么知名的复杂的语言,肯定还有更多东西我们还没了解,接下来就来介绍这些特性:类型成员、类的成员的类内初始值、可变数据成员、内联成员函数、从成员函数返回*this、如何定义并使用类类型以及友元类的更多知识。

类成员再探

我们现在先来定义一个类,Screen屏幕类:

class Screen
{
public:
    typedef string::size_type pos; //类型别名,别忘了啊
    Screen() = default //强制生成默认构造函数

    //自定义构造函数,别忘了这个初始化方式
    Screen(pos ht, pos wd, char c): height(ht), width(wd), contents(ht*wd, c){}

    //定义在类内部的成员函数都是隐式的内联函数
    char get() const //别忘了这边的const是干啥的
    {
        return contents[cursor]; //读取光标中的字符
    }

    inline char get(pos ht, pos wd) const; //显式内联声明,重载哦
    Screen &move(pos r, pos c); //函数声明

private:
    pos cursor = 0;
    pos height = 0, width = 0;
    string contents;
};


inline //在类外面定义内联函数
Screen &Screen::move(pos r, pos c)
{
    pos row = r * width; //计算行的位置
    cursor = row + c; //列
    return *this; //返回左值对象
}
//重载get函数
char Screen::get(pos r, pos c) const
{
    pos row = r * width;
    return contents[row + c];
}
//其实在声明和定义处都写inline也可以,推荐在类外面写,更易理解

以上也得出了一个结论,要想写非内联的成员函数,只能在类内声明在类外不用inline定义。

强行可变数据成员

这个应用很少,我觉得这个设定有点奇怪,理解倒是好理解的,你自己看代码吧:

class Screen
{
public:
    void some_member() const; //成员函数声明

private:
    mutable size_t access_ctr; //mutable即使在const对象内也能被修改
}

void Screen::some_member() const
{
    ++access_ctr; //你看,可以改变吧
};
类数据成员的初始值

在定义好Screen类后,我们要来定义一个窗口管理类Window_mgr,用它来表示显示器上的多个Screen(因为屏幕上可以出现多个窗口),这个类应该包含一个Screen的vector。在默认情况下,我们希望这个类有一个默认初始化的Screen,这时候就可以用到类内初始值了:

class Window_mgr
{
private:
    vector<Screen> screens{ Screen(24, 80, ' ') }
}

过程是这样的:我们用了列表初始化去初始screens这个Window_mgr类的类内成员变量,在列表初始化内容中,我们调用了Screen类的构造函数去实例化一个匿名对象。


==接下来要搞个***了,我给Screen类添加一些函数以及调用它们的代码,你来判断有没有问题==

//定义,上面的寒素也都包括在里面,我不重复了
class Screen
{
public:
    Screen &set(char);
    const Screen &display();
};
inline Screen &Screen::set(char c)
{
    contents[cursor] = c;
    return *this;
}
const Screen &display()
{
    cout << this->contents << endl; 
    return *this;
}
//调用
Screen myScreen;
myScreen.move(4, 0).set('$'); //对吗,为什么
myScreen.display().set('*'); //对吗,为什么

第一个调用对,第二个错,因为第一个返回的是引用,是左值,是它的身份,所以可以连续调用;第二个错是因为display函数返回的是常量引用,无法通过常量引用去改变它的值。 那我们应该怎么办呢?简单的方法是,你把display函数的const去掉就好了啊,但是我们觉得不妥,因为display函数不改变对象内容,设置成const是一个很好的行为,我们的解决办法是重载:

class Screen
{
public:
    Screen &display()
    {
        do_display();
        return *this;
    }
    const Screen &display()
    {
        do_display();
        return *this;
    }
private:
    void do_display() const
    {
        cout << this->contents << endl;
    }
};

我们把打印的任务交给了一个private函数,对外的接口是两个重载函数,试着来调用一下这样行不行:

Screen myScreen(2, 4);
const Screen blank();
myScreen.display().set('*'); //对
blank.display(); //对
blank.display(); //错

就解释到这儿了,欢迎讨论啊,不知道我的理解对不对。

类类型

每个类定义了唯一的类型。对于两个类来说,即使它们的成员完全一样,这两个类也是不同类型,不能互相赋值(我的理解是,类的名字也算类的类型,所以它们不同),我们使用类类型就跟在、使用内置类型一样的定义,这也是C++赋予我们的方便:

int a;
Screen b;
类的声明
class Screen;

向程序中引入名字Screen并且指明它是一种类类型,但是我们不知道它里面有什么。

对于一个类来说,我们必须定义它之后再去创建它的对象,不然编译器不知道给你这个对象分配多少内存。
得到一个结论,一个类的成员类型不能是它自己,但是可以是它的指针或者引用。

友元再探

这一段我就总结了一句话,都可以是朋友。

类之间的友元
class Screen
{
    friend class Window_mgr;    
    //Window_mgr可以访问Screen所有成员
}
令成员函数成为友元

这个之前引出友元概念的时候就介绍了:

class Screen
{
    friend void Window_mgr::clear();    
    //这里是跟人家的成员函数做朋友
}
函数重载和友元

a和b是重载函数,a是Screen的朋友,不代表b也是,一句话,把重载函数看成不同的函数

友元函数和作用域

这个书上的讲法它拗口了,看了我半天,总结如下,必须在类外部声明友元函数之后,类才能去调用它:

struct X
{
    friend void f(){} //友元函数,定义在类内部
    X(){ f(); } //默认构造函数调用f
    //这种调用时错误的,因为f没有被声明

    //俩成员函数的声明
    void g();
    void h();
}

void X::g(){f();} //错误,f没有被声明
void f(); //好,现在声明了
void X::h() {f();} //这样就对了

还有一个问题,我怎么才能在构造函数中调用友元函数呢?我觉得是不行的,欢迎讨论。

#C++工程师#
全部评论
在类的外部之前声明一下,构造函数就可以调用友元函数了呀~
点赞 回复 分享
发布于 2018-10-06 12:38
构造函数可以调用友元函数,构造函数的定义必须在友元函数的声明之后
点赞 回复 分享
发布于 2018-10-07 23:20
抄你点代码,做笔记
点赞 回复 分享
发布于 2019-04-18 15:54
抄你点代码,做笔记
点赞 回复 分享
发布于 2019-09-11 16:06

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
评论
6
收藏
分享
牛客网
牛客企业服务