<C++基础学习二十三>定义抽象数据类型
摘要: 本篇博客仅作为笔记,如有侵权,请联系,立即删除(网上找博客学习,然后手记笔记,因纸质笔记不便保存,所以保存到网络笔记)。
一、定义成员函数
成员函数必须在类的内部声明,但是成员函数体可以定义在类内也可以定义在类外。成员函数通过一个名为this的额外隐式参数来访问它的那个对象。所以所有的非static成员函数都有一个隐式参数this指针,this指针是一个指针常量,我们不允许改变this指针中保存的地址。而且该this指针是作为成员函数的第一个形参。
class Test{ public: void add(int i){_i += i;} //实际函数的形式是void add(Test *const this,int i) private: int _i = 0; }
我们可以通过在成员函数的形参列表后增加一个const关键字,来将成员函数声明为一个常成员函数。常成员函数的实际意义其实是把this的指针的类型从指向非常量对象的常指针,声明为指向常量对象的常指针。
class Test{ public: void add(int i) const {_i += i;} //实际函数的形式是void add(const Test *const this,int i) }
将this指针声明为一个指向常量对象的常指针,这样的成员函数中就不可以通过this指针改变此对象中的值。常量对象以及常量对象的指针或引用都只能调用对象的常量成员函数。(从函数形参匹配的角度容易理解此性质)
编译器在编译类时,首先编译成员的声明,然后才编译成员函数的函数体,因此,成员函数体内可以随意使用类中的其他成员函数而无需在意这些成员出现的次序。
另外在类外定义的函数形式必须要与类内声明函数的返回类型、参数列表、函数名完全匹配,所以如果类内声明了一个函数为常成员函数,那么类外定义时也必须加上const声明。(这样才能使参数列表完全匹配)
二、定义类相关的非成员函数
一般来说,如果非成员函数是类接口的组成部分,则这些函数的声明应该与类在同一个文件中。
三、构造函数
类可以包含多个构造函数。构造函数不能声明为const,因为当我们创建类的一个const对象时,直到构造函数完成初始化过程中,对象才能真正取得其常量属性。
四、合成的默认构造函数
无任何实参的构造函数就是默认构造函数。如果我们的类没有显示定义任何默认构造函数,那么编译器会为类合成一个默认构造函数。对于大多数类来说,这个合成的默认构造函数会按照如下规则初始化类的数据成员:
1、如果存在类内的初始值,则用初始值初始化此数据成员
2、如果不存在类内的初始值,则编译器将默认初始化该成员。(此时,该数据成员将是随机值)。
五、=default
一旦我们定义了其他的构造函数,那么编译器将不会再为类合成一个默认的构造函数。如果此时我们需要一个默认的构造函数,我们可以通过在参数列表之后加=default来要求编译器生成一个默认构造函数,这是C++11新增的特性。
当然我们也可以通过构造函数初始值列表来赋予数据变量初值,而且列表中的初值将覆盖类内的初始值。
class Text { public: Text() = default; //要求编译器合成一个默认构造函数 Text(double d,int i = 1):_d(d),_i(i){} ~Text(); private: int _i = 0; double _d = 3.14; };
六、拷贝赋值与析构
除了定义类的构造函数外,类还需要控制拷贝、赋值和销毁对象时发生的行为。
如果我们不定义这些行为,编译器将为我们控制这些行为,通常我们不应该一来编译器默认合成的版本。