13、14、15章(类,类的初始化、赋值和析构,重载操作符和用户定义的转换)

来源:互联网 发布:vmware的ubuntu扩容 编辑:程序博客网 时间:2024/06/05 00:28
 
1、 类声明之后由于不知所分配的类对象的大小,不能定义类对象,类对象定义只能在完整的类类型定义之后。而由于指针的大小是固定的,故类声明之后就可定义指向类对象的指针。
Class A;   //类声明
A a; //不能通过编译
A *pa;     //可以通过编译
Class A
{};   //类定义
 
2、 由于inline函数必须在调用它的每个文本文件中被定义,故没有在类体中定义的inline函数必须放在类定义出现的头文件中跟在类体之后。即头文件要包括类定义及在类外部定义的inline函数的定义(这也是一种比较好的编程风格)。
 
3、 const 类对象只有从“构造完成时刻到析构开始时刻”被认为是const的,故const类对象只能调用const成员函数、构造函数和析构函数,而普通类对象则可调用const的普通成员函数。其要注意以下几点,其一:const成员函数必须在其声明和定义中都显式的指定const;其二:const成员函数可被同参数表的非const成员函数重载,而由类对象的常量性决定调用哪个函数;其三:const成员函数保证不修改类的数据成员,但该类若有指针成员变量,则在const成员函数中能修改指针所指向的对象,但这是一种不好的编程风格;其四:mutable声明类的数据成员为可修改的,即使它是一个const对象的数据成员,同样,在const成员函数中也可以修改被声明为mutable的数据成员。
 
4、 类的内联函数只在函数声明或函数定义中指名inline即可;类的const成员函数必须在声明和定义中都指名const;类的static成员函数和 static成员数据只在类中声明为static,不能在类体外的函数定义和成员数据初始化中显式指定static,且静态成员函数不能声明为 const。注意静态数据成员不能在该类定义中初始化,必须在类的实现文件中初始化;静态成员函数没有this指针,故在静态成员函数中隐式或显式的引用 this指针都将导致编译错误,故可以推论出静态成员函数不能访问非静态数据成员。
 
5、类成员的指针必须总是通过特定的对象或指向该类类型的对象的指针来访问,其指针声明需要显示指定所属类类型(因为其函数隐式传递了一个this指针),如 int (class::*pf) () = &class::func;。而静态类成员属于该类的所有对象,他们的指针是普通指针。

6、 在处理作为类成员的联合(union)对象时,为所有的union数据成员的类型提供一组访问函数,并定义一个union判别式来跟踪当前被存储在union对象中的值的类型。
 
7、 类域中的程序文本包括类体、类体外部成员定义的从被定义成员标识符开始到定义结束位置的域以及类体外部的静态数据成员定义从定义的静态数据成员标识符开始到定义结束位置的域。
 
8、 名字解析:只有在名字解析成功之后,编译器才会检查访问许可和类型兼容性。1、类体中出现的名字解析(inline函数定义中的名字和缺省实参名例外)先考虑名字使用之前出现的类成员的声明,在考虑类体之前的名字空间中出现的声明。2、类体中的inline函数定义中的名字和缺省实参名字解析,inline 函数声明中的名字考虑之前的类定义和名字空间的声明,inline函数体和缺省实参先考虑类中所有的成员声明,再考虑在类体之前的名字空间中出现的声明。 3、类体外部的类成员函数和静态成员定义的名字解析,首先考虑在函数局部域内出现的声明,再考虑类中所有的成员声明,最后考虑在成员函数定义之前的名字空间中的声明(而不是类定义之前名字空间的声明)。两个原则一是只有在名字解析成功之后,编译器才会检查访问许可和类型兼容性,二是解析过程对于类域考虑所有的成员声明(对于函数定义和静态成员定义),而对于名字空间总是只考虑定义名字之前的名字空间。
 
9、 关于嵌套类:1、嵌套类,外围类都没有特权访问彼此的私有成员,一种比较好的设计方法是把嵌套类成员声明为公有的放在外围类的私有区中。2、若嵌套类体中没有inline的定义成员函数,就必须在最外围的类之外定义这些成员函数,并用外围类名限定修饰嵌套类名。3、一个类的私有成员(函数,静态数据,嵌套类)可只在private区中声明,而在类外定义(注意不要忘记名字限定符修饰)。4、嵌套类由于this指针不匹配,故不能直接访问外围类的非静态成员,但可以直接访问外围类的静态成员,类型名(用typedef定义),枚举值等。
 

10、构造函数的执行过程可被认为分为两个阶段:1、隐式或显式的初始化阶段,前者没有成员初始化表,而后者则有。2、由构造函数体内所有语句构成的一般计算阶段,数据成员的设置被认为是赋值而不是初始化,故类的const和引用数据成员必须在成员初始化表中被初始化。最后要注意初始化的顺序为成员在类中声明的顺序,而不是名字在初始化表中的顺序。为了节省开销,有个一般性的规则是在成员初始化表中初始化所有成员类对象。

11、C++不能高效率的返回一个类对象,一般的解决办法是将通过参数返回一个类对象的引用。但这里有个疑问,若在函数体类声明一个静态局部类对象,返回其值的引用给调用此函数的一个引用赋值,又能够做到高效率。如下面的代码:
 Matrix& operator+( const Matrix& m1, const Matrix& m2 )
{
static Matrix result = m1+m2;
return result;
}
但是又有了新的问题,如
Matrix m1, m2, m3, m4, m5;

m5 = (m1+m2)+(m3+m4);

很明显,局部静态对象被非法的多次使用了。
 

12、若没有在类体中声明相关函数,则编译器会自动为一个类提供缺省构造函数,拷贝构造函数,重载的赋值操作符和析构函数。注意:其一对于缺省构造函数只要类定义中声明了任何一个构造函数,则其不再提供;其二是只要声明了就不再提供,不一定非要定义,但若声明了不定义,则编译出错。
 

13、关于重载操作符:1、类中定义的重载操作符,左操作数是该类类型的对象,且通过this指针隐式调用,=、[]、()、->操作符必须被定义为类成员操作符。2、全局重载操作符由于没有隐式的this指针作为隐式的第一个参数,故比类成员重载操作符多一个参数,一般的对于“对称操作符”(两个操作数同类型),最好定义为全局重载操作符。3、只能为类类型或枚举类型定义重载操作符,不能为内置数据类型定义其他操作符。且重载操作符对于优先级,参数个数都不能改变,最后还有除了operator()之外,都不能提供缺省实参。4、重载操作符一定要意义清楚(即于本来意义相近),否则,宁愿不提供。

14、  几个重载操作符:

1、  重载=,必须return *this且返回类型为class&;

2、  重载[]由于必须出现在一个赋值操作符的左右两边,故返回类型必须指定为一个引用;

3、  重载()被用在类类型被定义为表示一个操作时;

4、  重载->被重载为一元操作符,其返回类型必须是一个类类型指针或是“定义该成员访问操作符箭头的类”的一个对象。如果是前者,则内置成员访问操作符箭头语义被应用在返回值上。如果是后者,则递归应用该过程,直到返回的是指针类型或语句错误。

5、  重载++和--后置操作符的声明有一个额外的int类型的参数(class& operator++(int);)以和前置重载想区别,其隐式调用为class_obj++;,显示调用为class_obj.operator(1024),1024是任意的int数值,将被忽略掉。

6、  前四种操作符都必须定义为类的一个成员函数。


 
原创粉丝点击