类是C++里重要的扩展机制,可以提供语言本身不支持的能力,设计良好的类类型使用起来和内置类型一样方便。标准库就是类的一种实际案例,之前的程序里我们使用的vector、string、ostringstream都是标准库给我们定义的类。
1.类的声明
类可以只声明,而不定义,没有定义的类称为不完全类型,比如下面的Animal类,只知道它是个类型,不知道有哪些成员
class Animal;
2.类的定义
类声明的右侧可以直接加一对大括号,完成类的定义,一旦定义完成,类的成员就已经确定,编译器也就能计算存储一个该类类型的对象要多少存储空间。一个类如果在多个文件中定义,必须完全相同。一般来说我们会把定义放到头文件中。以Animal类为例,类定义放到Animail.h中,并使用头文件保护符避免重复定义
#include <string>
#ifndef clazz_animal
#define clazz_animal
class Animal {
public:
typedef unsigned short age_t;
Animal() :age(0) {
}
void run() const;
void grow_up() {
age++;
}
private:
std::string name;
age_t age;
};
#endif // !clazz_animal
类定义时,可以指定成员函数的定义,如grow_up,可以只声明函数,在类的外部再给出函数的定义。在类内部定义的函数默认是内联(inline)的。内联函数能避免方法调用带来的性能损耗,但只适用于实现简单的方法。仅仅完成了声明的成员函数,一般在源文件里定义,这里我们叫Animal.cpp
#include "Animal.h"
#include <iostream>
void Animal::run() const {
std::cout << "run..." << std::endl;
}
1.类的组成
从类Animal的定义可以看到,类有3类元素组成,类型别名,数据、函数。
2.访问标号
控制成员对外部的可见性,支持的标号有3种: public、protected、private。作用和Java里的基本一致。C++有两种定义类的关键字: class、struct。class关键字定义的类默认访问标号是private,struct关键字定义的类默认访问标号是public。
3.不完全类型
最前面我们提到只声明没定义的类是不完全类型。定义不完全类型的数据成员,只能是指向该类类型的指针或引用。当类定义自身类型的数据成员的时候,以为类没有定义完成,也属于不完全类型,因此也只能定义指向自身类型的指针或引用。定义指针或引用的原因是这两种定义不需要调用构造函数。
3. 成员函数
1.构造函数
构造函数是一种特殊的成员函数,函数和类同名,用于对类的数据成员做初始化。如下面的示例,:开始到左大括号{之间的部分,称为初始化列表,初始化列表有字段名和右侧一对小括号组成,小括号的作用是调用数据成员对应类型的构造函数。
Animal() :age(0) {}
2.成员函数
成员函数必须在类内声明,可以在类内、类外定义。类内定义的函数默认是inline函数。在类外定义的函数,函数名之前要使用作用域符::,指定所属类名。
形参表右侧的const将函数声明为常量,函数内部不能修改对象的数据成员。const必须在声明和定义中都出现,否则报错。
void Animal::run() const
类内定义的函数默认是内联(inline)的,如果希望类外定义的函数也是内联,可以只类声明的时候显式的添加关键字inline。内联函数必须对每个源文件可见,因此即使是类外定义的内联函数,通常也和类定义放在一起,即放到头文件里。