1.类的概念
1)类是一种抽象数据类型(ADY),基本思想是数据抽象和封装。
2)数据抽象是一种依赖接口和实现分离的编程技术。类的接口包括用户所能执行的操作;类的实现包括类的数据成员、负责接口的函数以及定义类的各种私有函数。
3)封装实现了类的接口和实现的分离:隐藏类的实现细节,进对外公开接口
2.类的访问说明符
1)public声明公有成员,公有成员在类中、类外、派生类中可见
2)protect声明保护成员,保护成员在类中、派生类中可见
3)private声明私有成员,私有成员只能在类中可见
3.类的声明与定义
1)前向声明:就像可以把函数的声明和定义分离开一样,类也可以仅声明而暂时不定义,类似这样的声明称为前向声明
2)不完全类型:在类声明之后,定义之前,这个类是一个不完全类型
4.友元
1)类的友元可以访问类的非public成员
2)在类中用关键字friend作为前缀来声明,不受访问说明符的限制
3)友元函数可以在类外定义,也可以在类内定义,但必须在类内声明不能在类外声明,因为友元的声明是要指定它访问这个类的权限,在类内做指定编译器才会知道
4)同时,友元函数的声明也仅仅是指定访问这个类的权限,而非通常意义的函数声明,所以要使用它,最好在类外再专门声明一次(虽然编译器也可能不会报错),通常把友元的声明和类放在同一个头文件中
6)注意:友元关系不能传递,也不能继承
5.静态数据成员
1)设计初衷:类需要一些成员与类本身相关,而不是和类的对象相关,如:一个银行账户类需要一个数据成员来表示当前的利率(因为利率对于每个银行账户实例来说都是一样的);静态成员就是这样的成员,它属于整个类
2)在成员声明之前加上关键字static
3)静态成员可以是public、protect、private
4)静态数据成员一般在类中声明,类外定义;但有例外:如果该静态成员是常量表达式,就可以在类内初始化
class cfq { public: static const int a = 6; };
5)为什么为什么一般的静态数据成员不能在类内初始化:因为静态成员属于整个类,而不属于某个对象,如果在类内初始化就是在告诉编译器每个对象都包含该静态成员,这是矛盾的
6)在类的外部定义时,不能出现static,该关键字只能出现在类的内部
7)静态成员在类外可以用“类名::”来访问,也就是说,不通过实例化也可以调用;或者和非静态公有成员一样,通过对象调用(object.静态成员)
class cfq { public: static int fun() { return 100; } static int a; }; int cfq::a = 6; int main() { cout << cfq::fun() << endl; cout << cfq::a << endl; cfq cc; cout << cc.a << endl; --cc.a; cout << cfq::a << endl; return 0; } 程序输出: 100 6 6 5
8)成员函数(类内)可以不通过作用域运算符直接访问
9)静态数据成员可用于一些特殊场景:
- 静态数据成员可以是不完全类型(见代码),非静态数据成员不能是;因为静态成员不属于某个类对象,不是某个类对象的成员,不是类对象的一部分,不存在嵌套包含的问题
- 可以使用静态数据成员作为函数的默认实参
class cfq { public: static int a; static cfq bb; cfq hehe;//错误:非静态数据成员不能使不完全类型 }; int cfq::a = 6; int func(int x = cfq::a)//静态数据成员作为默认实参 { return x; } int main() { cout << func(); return 0; } 程序输出: 6
10)基类定义的静态成员, 将被所有的派生类共享
6.静态成员函数
1)用static修饰的成员函数
2)属于整个类,所以没有this指针,所以不能声明成const,所以在函数体中也不能访问非静态成员,只能访问静态成员
3)静态成员函数即可在类内定义,也可在类外定义
4)静态成员函数不能被virtual修饰:
- 因为静态成员函数属于整个类不属于类的实例,基类的静态成员函数被派生类共享,所以加上virtual没有任何意义
- 静态成员函数不属于类的实例,所以它没有this指针,而虚函数有this指针
5)带来的好处:1.设计初衷(见上);2.调用方便,不需要实例化也可调用,此时,静态成员函数相当于一个带有命名空间的全局函数