****************************************************
ch11-类
****************************************************
1.C++中,结构体是用关键字struct声明的类,默认情况下成员是public的。
类中成员默认是private的。

2.类的定义中的成员函数:规模小,不能使用switch语句,即使没有用inline标示,也视为内联函数。

3.一个类的对象所占据的内存空间由它的数据成员所占据的空间总和决定,但不包括静态成员。
类的成员函数不占对象的内存空间。

4.类的作用域是指:类定义和相应的成员函数定义范围。

5.局部类:在函数中定义的类。很少见。局部类的作用域在定义该类的数据块中。
局部类的成员函数必须在类定义内部定义。

6.名空间:某名字在其中必须有唯一的作用域。
类型名:如int char long以及定义的类名
非类型名:如变量名、常量名、函数名、对象名或枚举成员
类型名和非类型名不在同一名空间。意味着:一个名字可以声明一个类型,又可以声明为一个非类型。例如:
class stat //类型名
{
//...
}

void stat() // 非类型名
同时登场时,类型名前面要加前缀,如class stat obj;


****************************************************
ch12-构造函数
****************************************************
1.构造函数没有返回类型,函数体中也不允许返回值,但可以有无值返回语句“return;”, 可以有参数,可以重载。
析构函数没有返回类型,没有参数,不能随意调用,不可以有参数,不可以重载。

2.如果有多个重载的构造函数,那么不可以在构造函数中调用其他的构造函数来初始化。
如果存在这样的情况,系统会理解为再创建一个无名对象。
解决:可以定义一个共享成员函数,每个重载的构造函数都调用它。

3.如果在类A成员中,包含其他类B的对象b,那么在定义类A的对象a时。
class B
{
public:
B()
{

}

B(int id = 0)
{
value = id;
}

~B(){}

private:
int value;
};

class A
{
public:
A(char *pName = "noName")
{
strncpy(name, pName, sizeof(name));
}

~A(){}

private:
char name[20];
B b;
};

A a("name"), 执行步骤如下:
(1)分配a对象空间,调用A构造函数,此时并未执行函数体。
(2)建立a对象空间中的结构,遇到类B的对象b时,调用B默认构造函数。所有结构建立完成后,返回到类A的构造函数。
(3)这才开始执行类A的构造函数体。

在类A的定义中,其构造函数A(char *pName = "noName"),其实相当于A(char *pName = "noName"):b(),标示在创建
成员b时,调用类B的默认构造函数。

如果想在定义对象a时,也对成员对象b进行初始化,那么可以修改类A的构造函数为:
A(char *pName = "noName", int nID):b(nID){...}
如此,冒号表示要对类A的数据成员b的自定义构造函数进行调用,实参时nID。

4.类中,常量和引用的初始化必须放在构造函数正在建立数据成员结构的时候,也就是放在构造函数的冒号后面。
在类构造函数的函数体中的操作,叫做赋值,不是初始化。

5.静态和局部对象,以声明的顺序定义,而不是以执行顺序来定义。



****************************************************
ch14-堆与拷贝构造函授
****************************************************
1.拷贝构造函数:即构造函数的参数是该类的引用。例如:
class A
{
public:
A(){} // 默认构造函数
A(int id){} // 自定义构造函数
A(A &a){} // 拷贝构造函数
};
拷贝构造函数用在对象的赋值以及函数调用时。例如:
A a;
A b = a; // 调用拷贝构造函数

当一个被调用函数的参数是类对象时,那么从实参到形参的之间,传递过程是:
(1)在被调用函数的栈空间分配一个局部对象a的空间。
(2)调用拷贝构造函数,使用实参对象的数据成员来构造局部对象a的数据。

2.如果未提供自定义的拷贝构造函数,则C++会提供一个默认拷贝构造函数,其工作方法是完成一个成员一个成员的拷贝。
如果成员是类对象,则调用其拷贝构造函数或者默认拷贝构造函数。

3.浅拷贝:资源没有复制,2个对象共享同一个资源。
深拷贝:资源也进行复制,2个对象资源不是同一个。
C++默认拷贝构造函数是浅拷贝,如果需要深拷贝,需要自定义。

在析构函数中,如果需要析构资源,那么该类也需要一个深拷贝的拷贝构造函数。

4.C/C++函数返回值时,会利用一个临时变量或临时对象保存数据,
如果是简单类型,会保存在寄存器中(x86通常是eax),如果是比较复杂的自定义类型,编译器会开辟一块内存空间来存放。
该临时变量或临时对象的生命周期是:创建它们的外部表达式范围内。

5.类型转换
class student
{
public:
student(char *){}

...
};

可以把一个字符串转换成student类对象,因为类student中有student(char *){}这个构造函数。


****************************************************
ch15-静态成员与友元
****************************************************
1.静态数据成员,在程序一开始运行时就必须存在,而且必须放在类的实现文件中定义。

2.访问静态数据成员
class Student
{
public:
static int totalNum;
};

Student stu1, stu2;
stu1.totalNum; // 合法,编译器只取对象stu1所属的类型Student
stu2.totalNum; // 合法
Student::totalNum; // 合法,常用

3.静态成员函数只能访问静态成员数据。

4.静态成员函数与非静态成员函数的根本区别:静态成员函数没有 this 指针。
class Student
{
public:
void nsFunc(int a); // 相当于 Student::nsFunc(Student *this, int a);

static sFunc(int a); // 相当于 Student::sFunc(int a);
};

调用时:
int main()
{
Student stu;

stu.nsFunc(10); // 转换为 Student::nsFunc(&stu, 10);

stu.sFunc(10); // 转换为 Student::sFunc(10);
}