目录
本文基于西工大网课总结,总结的不好请见谅
类的定义
1. 定义类
三大特点
- 抽象:对具体问题概括,抽出一类对象的公共性质
- 数据抽象
- 行为抽象
- 封装:数据成员与行为成员相结合,视为一个整体——类
- 继承与派生:保持原有特性的基础上,进行更具体的说明
如何定义一个类
- 类:用户自定义数据类型,定义形式如下
class 类名{ 成员列表 };
说明:
- 成员列表是类成员的集合,数目可以任意多
- 大括号{ }是成员列表边界符,与成员列表一起称为类体
- 类体后面必须用分号(;)结束
- 类成员可以是数据或函数
- 所有成员必须在类的内部声明,一旦定义完成则无法添加成员了
数据成员
- 类定义时必须给出各个数据成员的数据类型声明
- 声明成员列表用**(,)作为间隔,最后以(;)**结束
成员函数
- 成员函数可访问自身的所有成员
- 成员函数作为对外界的接口,通过成员函数访问数据
- 若类中有成员函数,声明成员函数是必须的,定义成员函数是可选的
-
在类中*定义(声明)*成员函数
class 类名{ 返回类型 函数名(形参列表) { 函数体 } };
-
在类中声明成员函数
class 类名{ 返回类型 函数名(形参列表); }; 返回类型 类名::函数名(形参列表) { 函数体 }
实例如下
class Data{ void set(int d); int get(){ return data; } int data; }; void Data::set(int d) // 成员函数的外部定义 { data=d; }
-
类定义位置
- 类定义一般放在程序开头或头文件中,作用于全局
- 类定义也可以放在函数内部,作用于局部
class Data{ // 作用于全局
void show();
int data;
};
void fun()
{
class Data{ // 作用于fun函数内部
void show();
int data;
};
}
说明:
- 在局部作用域中声明的类,成员函数必须是函数定义的形式,不能是原型声明,类很少放到局部作用域中定义
- 类是一种数据类型,类型声明不会产生该成员的实体
2. 成员的访问控制
访问来源
- 类成员
- 类用户
说明:
类成员:类本身的成员函数
类用户:类外部的使用者,包括全局函数、另一个类的成员函数等
访问权限
- public(公有的):实现了类的外部接口
- private(私有的):实现了私有成员的隐蔽
- protected(保护的):不考虑继承的情况下,性质与private相同,可以被派生类的类成员访问
定义形式
class 类名{
int a, b; // 默认为私有的,外部不能访问
public: // 公有访问权限,外部可直接访问
//公有的数据成员和成员函数
void set(int i, int j, int k, int l, int m, int n)
{
a=i,b=j,c=k,d=l,e=m,f=n;
}
protected: //保护访问权限,外部不能直接访问,派生类可以访问
//保护的数据成员和成员函数
int c, d;
private: //私有访问权限,外部和派生类都不能访问
//私有的数据成员和成员函数
int e, f;
};
说明:
- 如果没有声明访问属性,则默认为private属性
- 声明为public、private、protected的成员次序任意
- public、private、protected关键字可以出现任意多次,但更通用的方法是把相同访问属性的数据成员和成员函数写在一起
- 实际编程中为了是程序清晰public、protected、private只出现一次,且按照public、protected、private的顺序组织
3. 类的数据成员
在类中声明数据成员
-
类的数据成员声明类似于普通变量的声明
class Cube{ long color; double x, y, z, side; };
-
类的数据成员可以是基本类型、数组、指针、引用、共用体、枚举、void指针、const限定等数据类型
class ADT{ long color; double x,y,z,side; int a[10]; char *s; char &r; void *p; };
-
类的数据成员可以是成员对象,即类类型或者结构体类型的对象。
class Point{ public: void set(int a, int b); int x, y; }; class Line{ public: void set(Point a, Point b); Point start, end; // 成员对象 };
在类中定义或声明数据类型
- 除了数据成员和成员函数,类还可以定义自己的局部类型
- 在类中定义或声明的数据类型作用域为类内部,所以自定义的数据类型不能作用于类外部
- 在类定义中,可以定义结构体和共用体类型、嵌套的类定义,声明枚举类型
class ADT{
struct Point {int x, y;}; // 定义结构体
union UData {Point p; long color;}; // 定义共用体
enum COLORS {RED,GREEN,BLUE,BLACK,WHITE}; // 定义枚举类型
class Nested{ // 嵌套类定义
//成员函数
Point start;
UData end;
COLORS color;
};
typedef Point* LPPOINT; // 声明类型别名
};
4. 类的成员函数
在类的外部定义成员函数
-
如果成员函数仅有声明在类定义中,则在类的外部必须有它的实现,形式如下:
class Data{ //Data类的定义 public: void set(int d); // 成员函数声明 int get(){ // 成员函数定义 return data; } private: int data; }; void Data::set(int d) // 成员函数的外部定义,使用Data::限定 { data = d; // 访问类的数据成员 } void set(int d) { ... // 函数体 }
说明:
- ::是作用域限定符,如果作用域限定符前没有类名或没有作用域限定符,如::set(10)、set(10),则表示set函数不属于任何类,而是全局的普通函数
- 在成员函数中可以访问这个类的任何成员
- 类的成员函数原型声明必须出现在成员函数定义之前,因为在成员函数的定义在类的外部时,调用成员函数会根据在类中的声明的函数原型找到函数的定义
- 在类中声明成员函数,在类外定义成员函数是良好的编程习惯,有助于类的接口和实现分离
- 如果成员函数的函数体不太复杂,仅有4-5行,一般可在类中定义
内联成员函数
- 默认情况下,在类体中定义的成员函数若不包括循环等控制结构,符合内联函数时,C++会自动将它们作为内联函数处理(隐式inline)
- 也可以显式地将成员函数声明为inline
成员函数重载及默认参数
-
可以对成员函数重载或使用默认参数
class MAX{ int Max(int x, int y) { return x>y?x:y;} int Max() { return Max(Max(a,b), Max(c,d)); } // 重载Max int Set(int i=1, int j=2, int k=3, int l=4) { a=i, b=j, c=k, d=l; } // 默认参数 int a, b, c, d; };
说明:声明成员函数的多个重载版本或指定成员函数的默认参数只能在类内部进行
成员函数的存储方式
- 用类实例化一个对象时,系统会为每一个对象分配存储空间,且分别为数据和函数的代码分配存储空间
- C++会为每个对象的数据成员分配各自独立的存储空间
5. 类的声明
-
在一个给定的源文件中,一个类只能被定义一次
-
通常将类的定义放在头文件中
-
可以只声明一个类而不定义它,此声明称为前向声明。在声明之后,定义之前,该类是一个不完全类型,只能用于定义指向该类的指针和引用,或者用于声明使用该类型作为形参类型或返回类型的函数,在使用指针或引用访问类的成员之前,必须已经定义类。
-
类不能具有自身类型的数据成员。然而,只要类名一经出现就可以认为该类已声明,因此,类的数据成员可以是指向自身类型的指针或引用
class Point; // Point类声明,非Point类定义,因为没有类体 class Line{ Point a; // 错误,不能使用仅有类声明而没有类定义的数据对象 Point *pp, *rp; // 正确,只有类声明,即可用它定义该类的指针或引用 Line b; // 错误,类不能具有自身类型的数据成员 Line *pl, &rl; // 正确,类可以指向自身类型的指针或引用 };