C++ Primer 类 12.1-12.2 this ,定义

原创 2016年05月30日 14:59:04

12.1 类的定义和声明

类由类成员组成。类成员包括属性,字段,成员函数,构造函数,析构函数等组成。 

类设计应该遵从抽象封装性。

类抽象性指对于类的使用者来说只需知道类接口即可使用类功能。类的具体实现由设计者负责。即使某个功能发生了变更但由于使用者是以接口方式调用类所以用户代码无需做任何修改。

类封装性指类用户只需知道类的功能无需了解具体实现。实现代码对用户来说不可见。 

C++类没有访问级别限限制,定义类时不能用public 或 private 做修饰。类成员有访问级别,可以定义 public protect private

#include<iostream>

using namespace std;

 

class Screen

{

            public:

                         //类成员只能声明不允许定义 替换成stringname("tom")

                        //会产生编译错误, 数据成员初始化工作在构造函数中执行

                        string  name;           

 

                        // 给类定义别名类型成员 index 由于别名要在外部访问所

                        //以一定要定义在 public

                        typedefstd::string::size_type index;

 

                        //构造函数

                        Screen( index cur =100);

 

                        //析构函数

                        ~Screen();

 

                        // 内部定义的函数,等价于inline

                        char get() const {return contents[cursor]; }

 

                        // 内部声明一个成员函数(无定义),且函数是内联的inline

                        //表示在编译时该声明会被替换成定义语句

                        inline char get(indexht, index wd) const;

 

                        // 内部声明一个成员函数(无定义)

                        index get_cursor()const;

 

            private:

                        std::string contents;

                        index cursor;

                        index height,width;

};

 




#include<iostream>

#include"def_class.h"

using namespace std;

 

inline Screen::Screen(Screen::indexcur ){

            cursor = cur;

            width = 20;

            height = 10;

}

 

inlineScreen::~Screen(){

 

}

 

// 定义类 Screen 的成员函数get 具体实现

charScreen::get(index r, index c) const

{

 

            index row = r * width;    // compute the row location

 

            return contents[row + c]; // offsetby c to fetch specified character

 

}

 

 

// 定义类 Screen 的成员函数get_cursor 具体实现,且是内联的

 

inline Screen::indexScreen::get_cursor() const

//inline indexScreen::get_cursor() const

{

 

            return cursor;

 

}

 

#include<iostream>

#include"def_class.h"

 

using namespace std;

 

int main( int argc ,char *argv[] ){

            Screen wnd;

            size_t cur;

 

            /* operate member function */

            cur = wnd.get_cursor();

            cout<<cur<<endl;

 

            return 0;

}


注:1.类的inline修饰符可以放在类内部申明也可以放在外部定义。一般放在内部声明便于理解。

类定义完毕后一定要加上封号结束符;。

类数据成员只允许声明不允许定义;

2.编译的时候应该这样

g++ -fkeep-inline-functions main.cpp def_class.cpp

分析原因,由于def_class.h所有函数在实现文件def_class.cpp中均显式声明为内联,根据g++编译的默认选项是-fno-keep-inline-functions,如果函数被内联,则不存在对函数的调用,编译程序将不生成函数体,因此虽然main.cpp中include了相关函数的定义,但是找不到这些函数的实现,自然出现错误"undefinedreference toXXX"。 
修改该选项为-fkeep-inline-functions,则及时不存在对函数的调用,编译程序也会生成函数体,于是世界又清静了。



12.2 this指针

1.这些函数的返回类型是 Screen&,指明该成员函数返回对其自身类类型的对象的引用。

2.在普通的非 const 成员函数中,this 的类型是一个指向类类型的 const 指针。可以改变 this 所指向的值,但不能改变 this 所保存的地址。

3.基于成员函数是否为 const,可以重载一个成员函数;同样地,基于一个指针形参是否指向 const( 7.8.4),可以重载一个函数。const 对象只能使用 const成员。非 const 对象可以使用任一成员,但非 const 版本是一个更好的匹配。

4. 类对象包含一个 this 指针指向自身(当前的实例对象)且无法更改指针指向。在普通的非 const 成员函数中,this 的类型是一个指向类类型的 const 指针。可以改变 this 所指向的值,但不能改变 this 所保存的地址。在 const 成员函数中,this 的类型是一个指向 const 类类型对象的 const 指针。既不能改变 this 所指向的对象,也不能改变 this 所保存的地址。

    基于成员函数是否为 const,可以重载一个成员函数;同样地,基于一个指针形参是否指向 const可以重载一个函数。

class mycls

{

    public:

        mycls(){}; // 想要定义 const mycls a; 必须要显示定义默认构造函数

        mycls &Get(){ return *this; };

        const mycls &Get() const { return*this; }; // 想如果const函数返回this引用或指针; 必须要返回const指针或引用,因为无法用const对象(this)初始化非const对象。

 

};

 

const mycls b;

mycls b1 = c.Get();// 调用const版Get函数

const mycls b2 =c.Get(); // 调用const版Get函数

// b1 b2 定义时会调用类的拷贝函数。b1,b2是Get返回值的副本,b1还会将常量副本转变成变量

 

mycls &b3 =c.Get(); // 错误,不能用 const &mycls 初始化 &mycls (指针或者引用类型不能用常量初始化变量)

const mycls &b4 =c.Get();

 

 

mycls a;

mycls a1 = a.Get();// 调用非const版Get函数

const mycls a2 =a.Get(); // 调用非const版Get函数

       由此可见调用那个版本和调用对象是否const有关系,const对象会调用const版本,非const对象会调用非const版本。   

       引用网上的总结:

成员函数具有const重载时,类的const对象将调用类的const版本成员函数,类的非const对象将调用非const版本成员函数。

如果只有const成员函数,类的非const对象也可以调用const成员函数。                         ——这个思路来描述很囧。下同。

如果只有非const成员函数,类的const对象…额,不能调用非const成员函数。               ——其实跟上一句的意思是一样的:const对象只能调用它的const成员函数。

总的来说,就是当我们调用一个成员函数时,编译器会先检查函数是否有const重载,如果有,将根据对象的const属性来决定应该调用哪一个函数。如果没有const重载,只此一家,那当然就调用这一个了。这时编译器亦要检查函数是不是没有const属性而调用函数的对象又有const属性,若如此,亦无法通过编译。

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

C++ primer 第五版 中文版 练习 12.2 个人code

C++ primer 第五版 中文版 练习 12.2 题目:编写你自己的StrBlob类,包含const 版本的 front 和 back 。 答:

C++12.2 隐含的this指针(不懂)、mutable数据成员

简介7.7.1节 12.1.3节===================================================================================...

C++primer plus第六版课后编程题答案12.2

string2.cpp #include #include #include using namespace std; static int num_string;//不是在h头文件中只能在这...

c++primer 3/7--类作用域,隐含的 this 指针

一般的数据或函数成员必须通过对象来访问。定义类型的成员,如 Screen::index,使用作用域操作符来访问。类使用作用域操作符(::) class Screen { public:...

重温《C++ Primer》笔记五 类定义中成员函数的名字隐藏(虚函数与非虚函数)

类定义中大致有两种函数——普通函数和虚函数。如果对一个类继承并且对其中的成员函数重新进行定义,也可以分为两种情况: 1、在派生类的定义中明确地定义操作和返回类型,称之为普通成员函数的重定义(rede...

C++ Primer 笔记--13章:定义值型类

要使指针成员表现得像一个值,复制 HasPtr 对象时必须复制指针所指向的对象。 复制构造函数不再复制指针,它将分配一个新的 int 对象,并初始化该对象以保存与被复制对象相同的值。每个对象都保存属...

C++:对象数组、对象动态申请和释放、类的定义和实现分开、this指针、常成员函数、时钟

一、对象数组的定义和初始化 1. 对象数组的创建方法:   //常量都是无名对象 1)类类型 数组名[元素个数]; 2)类类型 数组名[元素个数] = { 数组的初始化列表... }; 2. ...

根据C++ Primer 5th编写的自定义String类

String.h String.cpp Test.cpp

C++Primer Plus 第十章-this指针

C++Primer Plus 第十章-this指针

C++ primer 【笔记】C++中this指针的用法详解

本文转自: C++的一大误区——深入解释直接初始化与复制初始化的区别 不久前,在博客上发表了一篇文章——提高程序运行效率的10个简单方法,对于其中最后一点,多使用直接初始化,有很多读者向我提出了疑问,...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)