前言
记录看过的知识点,有太多东西需要学习,一件一件来吧。
类
1,类包含类头和类体。类头由关键字class及其后面类名构成;类体由一对花括号包围起来。类定义后面必须接分号或声明;
2,在类体中对类的数据成员和成员函数进行声明,并指定这些成员的访问级别。类体中所有成员构成类成员表;
3,类成员访问级别实质是为了信息隐藏,即防止程序的函数直接访问类类型的内部表示而提供的一种形式化机制。访问级别通过访问限定符:public/private/protected指定:
- public公有成员:在程序的任何地方都可以被访问;
- private私有成员:只能被成员函数和类的友元访问;
- protected受保护成员:对派生类derived class 就像public成员一样,对其他程序则表现得像private ;
4,每个类定义都是引入一个唯一的类,即使两个类的类型具有完全相同的成员表,它们仍是不同的类;
5,类定义不会引起存储区分配,只有在定义一个类对象时,系统才分配存储区;
6,友元: 以关键字friend开头,只能出现在类的声明中。友元机制允许一个类授权其他的函数访问它的非公有成员;
隐藏的this指针
1,每个类对象都将维护自己的类数据成员的一份拷贝,但不同类对象的类成员函数以及静态类数据成员只存在一份拷贝;
2,类成员函数可以引用自己的类成员而无需使用成员访问操作符;
3,(**)每个类对象能够通过仅存在一份拷贝的类成员函数识别访问自己维护的类数据成员,是因为存在一个指向被调用对象的隐藏this指针;
4,this指针指向被调用的类对象的地址;
静态类数据成员
1,每个类对象都将维护自己的类数据成员的一份拷贝,但静态类数据成员只存在一份拷贝;
同全局对象相比,静态类数据成员的两个优点:
- 静态数据成员没有进入程序的全局名字空间,因此不存在与程序中其他全局名字冲突的可能性;
- 静态数据成员可以是private成员,实现信息隐藏,而全局对象不能;
2,静态数据成员一般在该类定义之外被初始化;
3,在类体内初始化一个const静态数据成员时,该成员必须仍然在类体外定义,但不需要再赋初始值;
4,静态数据成员的定义可以引用类的私有成员;
<span style="font-family:SimSun;font-size:18px;">class MyClass {
// ...
private:
static const int NameSize = 16;
static const char name[NameSize];
};
const char MyClass::name[NameSize] = "MyName"; // NameSize为类的私有成员,此时不需要再用类名限定符修饰</span>
5,在类的成员函数中可以直接访问该类的静态数据成员而不必使用成员访问操作符;
6,非成员函数访问静态数据成员:1)通过类的成员访问操作符访问静态数据成员;2)加类名限定修饰的名字直接访问;
7,静态数据成员独特的使用方式:
- 静态数据成员的类型可以是其所属类,非static数据成员只能被声明为该类的对象的指针或引用;
<span style="font-family:SimSun;font-size:18px;">class MyClass
{
public:
// ...
private:
static MyClass mem1; // ok
MyClass *mem2; // ok
MyClass mem3; // 错误
}; </span>
- 静态数据成员可以被作为类成员函数的缺省实参,非static成员不能;
<span style="font-family:SimSun;font-size:18px;">class MyClass
{
public:
int var;
static int stcvar;
private:
int mem1( int = var ); // 错误: 被解析为非static 的Foo::var,没有相关的类对象
int mem2( int = stcvar ); // ok: 解析为static 的Foo::stcvar
int mem3( int = ::var ); // ok: int var 的全局实例
}; </span>
静态类成员函数
1,静态成员函数不能声明为const或volatile;
2,在类体外的函数定义不能指定关键字static;
3,静态成员函数没有this指针,在静态成员函数中隐式或显式地引用这个指针都将导致编译时刻错误;
4,调用静态成员函数方式与访问静态类成员方式一致;
类成员函数
1,成员函数的定义在类体内提供,这些函数将被自动作为inline函数处理;
2,两行以上的成员函数最好在类体外定义。类体外定义成员函数,成员函数名必须被其类名限定修饰;
3,类成员函数可以引用以及直接访问任何类成员;
4,公有成员函数集定义了类的接口。程序可以通过类的公有成员函数访问该类的私有数据成员,从而达到信息隐藏的目的;
5,私有成员函数只能被类的其他成员函数(和友元)调用,程序不能直接调用。(**)在实现抽象类时,私有成员函数为其他成员提供支持;
6,const成员函数,const关键字放在函数参数表与函数体之间。如果在类体外定义,则必须在声明及定义中同时指定const关键字;
- const成员函数不能修改类对象。但如果类对象中含有指针,则能修改指针所指向的内容;
<span style="font-family:SimSun;font-size:18px;">class MyClass
{
public:
void myclass_func(const string &parm) const;
private:
char *_text;
}
void MyClass :: myclass_func(const string &parm) const
{
_text = parm.c_str(); // 错误: 不能修改_text
for ( int ix = 0; ix < parm.size(); ++ix )
{
_text[ix] = parm[ix]; // 不好的风格, 但不是错误的
}
}</span>
- const成员函数能被相同参数表的非const成员函数重载。由类对象的常量性决定调用哪个函数;
<span style="font-family:SimSun;font-size:18px;">class MyClass
{
public:
void get_func(int data) const;
void get_func(int data);
}
void main()
{
MyClass test;
const MyClass c_test;
char ch = c_test.get(0); // 调用const 成员
ch = test.get(0); // 调用非const 成员
}</span>
7,volitale成员函数:如果一个类对象的值可能被修改的方式是编译器无法控制或检测的,则把它声明为volatile。定义与const类似;
8,const、volitale成员函数只能被const、volitale修饰的类对象、构造函数、析构函数调用;
9,mutable数据成员:该成员主要是针对const类对象中,需要进行修改的数据成员,它可以被修改更新;
总结
参考资料
《C++ Primer》