重读C++ Primer,记录一些之前不易觉察的知识点(12. 类)

1.inline函数

当函数在类内部定义时,默认为inline,即可不使用inline关键字说明。

函数声明或者定义时,只要一处使用inline关键字说明,即为inline函数,也就是说没必要声明和定义时都使用inline关键字。

inline 函数(包括成员函数和非成员函数)的定义必须在调用该函数的每个源文件中是可见的。inline 成员函数如果不定义在类定义体内 ,则其定义通常应该和类定义放在同一头文件中。这点比较重要,感觉自己好像之前没有将inline成员函数的定义放在头文件里呀。。。


2.类的前向声明(forward declaration)

前向声明是声明一个类而不定义它。在声明之后,定义之前,类是一个不 完全类型(incomlete type),即已知类型,但不知道包含哪些成员。

不完全类型(incomplete type)只能以有限方式使用。虽然不能定义该类型的对象。但是可以定义指向该类型的指针及引用,或者用于声明(而不是定义)使用该类型作为形参类型或返回类型的函数。在创建类的对象之前,必须完整地定义该类,而不只是声明类,这样,编译器才会给类的对象预定相应的存储空间。同样地,在使用引用或指针访问类的成员之前,必须已经定义类。

类不能具有自身类型的数据成员,但是可以拥有一类特殊的数据成员,即指向自身类型的指针或引用,因为只要类名一出现就可以认为该类已声明。


3.类的定义为什么必须以分号结束

因为类定义之后可以接一个对象定义列表,定义必须以分号结束。例如:

class Sales_item { /* ... */ } accum, trans;

不过将类定义和对象定义组合不是一种好的编码风格。


4.const重载

同名的非成员函数,使用const和非const形参能形成 重载,但要求形参必须为指针或者引用,如:

void fun(const int a); 和 void fun(int a);  //不能形成重载,并且编译报错。

void fun(const int& a); 和 void fun(int& a);   //重载OK。调用时,const形参调用const函数,反之亦然。

void fun(const int* a); 和 void fun(int* a);   //重载OK。调用时,const形参调用const函数,反之亦然。

同名的成员函数,const函数和非const函数也能形成重载,如:

void fun(int a); 和 void fun(int a) const;  //重载OK。调用时,const对象调用const成员函数,非 const 对象可以使用任一成员,但非 const 版本是一个更好的匹配。


5.构造函数的初始化列表

从概念上讲,构造函数分两个阶段执行:(1)初始化阶段;(2)普通的计算阶段。计算阶段由构造函数函数体中的所有语句组成。

初始化阶段,会对每个数据成员进行初始化。如果数据成员出现在初始化列表中,则按列表中的方式进行初始化。否则,使用与初始化变量相同的方式进行初始化。这分为两种情况,内置或复合类型的数据成员和类类型的数据成员。前者初始值依赖于对象的作用域:在局部作用域中这些成员不被初始化,而在全局作用域中它们被初始化为 0。后者运行该类型的默认构造函数。

在局部作用域中这些成员不被初始化,而在全局作用域中它们被初始化为 0。这句话的意思见下例:

class A
{
public:
	int a;
	char b[10];
};

A obj;

int main()
{
	A obj1;

	cout << obj.a << endl;     //OK
	cout << obj.b[0] << endl;   //OK
	cout << obj1.a << endl;   //ERROR
	cout << obj1.b[0] << endl;   //ERROR
}

类类型的数据成员,如果在初始化列表中没有指定初始化方式,则编译器会使用默认构造函数进行初始化。如果那个类没有默认构造函数则会报错。这种情况下,为了初始化数据成员,必须显示的在初始化列表中提供使用其它构造函数的方式。

const或者引用类型的数据成员,只能在初始化列表中进行初始化,不能在普通计算阶段初始化。

成员按照声明的次序进行初始化,如下例:

     class X {
         int i;
         int j;
     public:
         // run-time error: i is initialized before j
         X(int val): j(val), i(j) { }
     };
在这种情况下,构造函数初始化列表看起来似乎是用val 初始化 j,然后再用 j 来初始化 i。然而,由于i 首先被初始化,当使用尚未初始化的 j 值来初始化 i时就有问题了!在VS2010下,编译不报错,运行后,j的值正常,但i为未初始化的值。





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值