类的定义
面向对象的核心是类,它是C++在C语言原有结构的基础上扩展出来的概念,不仅增加了附属于类的成员函数,也增加了继承和虚函数等面向对象编程所需要的重要功能。从类创建出来的具体变量则叫作对象。对象可以看作是类的实例,每个对象占有着独立的内存空间,而类只是一个描述对象的抽象概念。
成员变量
类中可以定义各种成员变量,可以是基本数据类型,也可以是其他类的对象。它们的初始值需要在构造函数中指定,不然就会自动使用默认的初始值,在编程时可能会带来超出预期的结果。而在一个类的内部也可以再定义一个类,不过这个类的作用域将仅限于这个类中;如果是公有访问权限,可以使用作用域操作符“::”在外部访问。
成员函数
类中定义的函数叫作成员函数。成员函数在调用的时候需要像读取或修改成员变量那样加上对象的名字作为前缀,例如myObj.doSomething()。
成员函数可以在类中定义,也可以在类的外部定义。如果要在类外定义成员函数,我们首先要在类中声明成员函数,然后在类外定义时在函数名前面加上类名和作用域操作符“::”。
构造函数
与类同名的特殊函数,这样的函数叫作构造函数。构造函数的主要功能是初始化类中的成员变量,它往往会在类实例化(也就是创建对象)的时候被自动调用。
构造函数支持重载,没用参数的构造函数也叫作默认构造函数。在没有自定义构造函数的时候,系统会提供一个预置的默认构造函数,相当于把所有成员变量都初始化为基本类型的默认值。
创建对象
一个具体的类与基本类型一样,都是一种类型。对象与基本类型的变量一样,也存在内存分配的问题,一般情况会分配在栈上。
this指针
成员函数访问成员时有一个隐含的指针变量this,它的类型是指向当前实例的指针,指向的是调用成员函数的对象。
this指针对于实例化的类对象来说就是它自己的地址,可以使用this指针来取得整个对象本身。通过使用this指针,我们可以在构造函数中给参数使用与成员变量相同的名字而不会混淆。在类的成员函数中访问成员变量其实都是默认隐式地使用了this指针。
类和结构体的区别
结构体与类的区别是默认的访问控制符。结构体的默认访问控制符是public,而类的则是private。
构造函数
默认构造函数
一般的构造函数都会有参数用来初始化类的成员,而默认构造函数是没有参数的构造函数。在创建对象的时候如果对象名后面不加括号,那么系统就会调用默认构造函数。
一般情况下,我们会用默认构造函数制定一些类成员的默认值,就像C++中基本数据类型的默认值一样。
如果一个类没有任何构造函数,系统就会自动生成一个默认构造函数,这个构造函数遵循着基本数据类型的默认初始化规则。但在一些编译器下,声明不带参数却没有默认构造函数的对象有可能会直接报错。
重载构造函数
构造函数在重载的时候也满足一般函数的重载规则。
初始化列表
初始化列表位于参数列表和函数体之间,以一个冒号“:”开始,并用逗号隔开数个类似调用构造函数的初始化表达式。
其实在实际编程中,我们也可以使用类似的语法对基本数据类型的变量进行初始化。举例如下:
int num(5);
float fnum(3.4);
char ch(‘h’);
bool bval(false);
必须使用初始化列表的情况:常量成员、引用成员和没有默认构造函数的类成员。
虚函数与多态
多态(Polymorphism)是面向对象编程中极为重要的一个特性。所谓多态,就是为不同数据类型的实体提供统一接口。换句话说,就是不同的类可以共享一个函数,但是各自实现不同。基类和派生类的同名函数会有函数隐藏的问题,为了实现多态,我们还需要使用虚函数。通过使用基类的指针,我们就可以调用不同派生类中实现不同的同名虚函数。这个时候基类的虚函数版本是被隐藏的,我们需要使用作用域操作符“::”才能访问基类中被隐藏的函数。
虚函数使用virtual关键字,virtual关键字在派生类中可以省略,编译器会自动将相同函数签名的派生类成员函数也识别为虚函数,但为了可读性还是加上它比较好。然而,基类的virtual关键字却是必要的。除了virtual关键字之外,使用虚函数也需要基类的指针或引用,而不是基类本身。