类中默认访问类型是 private 结构默认访问类型是public
定义位于类声明中的函数都将自动成为内联函数,在类声明之外定义时若使其成为内联函数,需加 inline限定符
在类中创建常量用作数组长度等用途直接声明行不通,因为类只描述对象的形式,并没有创建对象,因此创建对象前,没有用于存储的空间。解决方法是
1.声明一个枚举,作用域为整个类
class Bakery
{
private:
enum {Months = 12};
double costd[Months];
}; //这种方式声明枚举并不会创建类数据成员。即所有对象中都不包括枚举
2.使用关键字static,该变量将与其它静态变量储存在一起,而不在任何一个对象中,被所有此类的对象共享,C++98中,只能使用这种技术声明值为整数或枚举的静态常量,不能存储double常量,C++11消除了这种限制
作用域内枚举(C++11) 也可用struct代替class
enum class egg {small,medium, large};
enum class t_shirt {small, medium, large, xlarge};
egg choice = egg::large; //使用
作用域内枚举不能隐式转换成整型,必要时可显式转换
作用域内枚举的底层类型为int, 语法enum class : short egg {...}; 提供了不同选择,也可指定常规枚举的底层类型
类的自动转换
当构造函数可以只接受一个参数时,赋值语句会调用构造函数生成临时变量然后再把该变量赋值
例. Stonewt myCat; //Stonewt为一个类,有构造函数Stonewt(double lbs);
myCat = 19.6;
与
Stonewt myCat = Stonewt(19.6); 等价
要关闭这种特征, 可在构造函数声明处加 explicit 关键字. explicit Stonewt(double lbs);
类的转换函数 添加到类声明中
operator typeName(); //typeName为基本类型,如int、double等。
无参数,无返回值,但仍要返回相应类型 (附.int转换为四舍五入)
C++98中 explicit 不能用于转换函数。 C++11可以,即让其必须显示转换
类的特殊成员函数
1.默认构造函数,如果没有定义构造函数
2.默认析构函数,如果没有定义
3.复制构造函数,如果没有定义,用于将一个对象复制到新创建的对象中,即用于初始化过程中,而不是常规赋值过程。
原型 Class_name(const Class_name &);
调用时间
String ditto(motto); //假设motto是String对象
String metoo = motto;
String also = String(motto);
String * ps = new String(motto);
生成对象副本时,如按值传递,返回对象
4.赋值运算符,如果没有定义
原型 Class_name & Class_name::operator=(const Class_name &);
自定义赋值运算符时应注意
由于目标对象可能引用以前分配的数据,应使用delete[]释放
应避免对象赋给自身,否则,给对象重新赋值前,释放操作可能删除对象内容
返回一个指向调用对象的引用
5.地址运算符,如果没有定义
(C++11) 移动构造函数
(C++11) 移动赋值运算符
静态类成员函数
函数声明前加static, 但定义前不加。不属于任何对象,没有this指针,只能使用静态数据成员
定位new分配的对象必须显式调用析构函数,
成员初始化列表
调用类的构造函数将导致程序首先给成员分配内存,再使用常规赋值方法将值存储到内存,因此, 对于const数据成员,必须在执行到构造函数体之前初始化。C++提供了成员初始化列表,只有构造函数可用
例. Queue::Queue(int qs) : qsize(qs),... //Queue为类,qsize为const数据成员,多个赋值逗号分隔
使用注意:
1.这种格式只能用于构造函数
2.必须用这种格式初始化非静态const数据成员 (至少在C++11之前是这样)
3.必须用这种格式初始化引用数据成员
派生类
派生类构造函数要点
1.首先创建基类对象
2.派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数
3.派生类构造函数应初始化派生类新增的数据成员
若派生类重新定义某方法,派生类调用时需加作用域解析运算符指明基类,否则将视为调用该派生类的函数
派生类与基类的关系
基类指针和引用可以在不进行显示类型转换的情况下指向派生类对象
但,基类指针或引用只能用于调用基类方法
不能将基类对象和地址赋给派生类引用和指针
virtual 方法
继承中如果没有virtual, 程序将根据引用类型或指针类型选择方法,如果使用了virtual 将根据引用或指针指向的对象的类型选择方法
抽象基类(ABC)
在类虚函数成员声明后加 = 0 可以把该函数变成纯虚函数,则类中可以不定义该函数,但也不能创建该类对象,只用作基类
在保护和私有继承中可以使用using声明(只使用成员名,无括号、特征标、返回类型)使基类的成员函数在继承类中可见(成为继承类的公有接口)
多重继承(MI)
应解决的问题
1.从不同基类继承同名的方法
2.从多个相关基类继承同一个类的多个实例
解决方式:
一种方法是使用类型转换转换成冲突类的派生类
另一种是继承此基类时用virtual 关键字使其成为虚基类(virtual与public次序无关),这样多重继承时只包含此基类的一个副本。
基类为虚时,为避免多条途径传递信息给基类构造函数,将忽略信息通过中间类自动传递给基类,编译器将使用基类的默认构造函数,如不希望则需显式调用所需的构造函数
定义位于类声明中的函数都将自动成为内联函数,在类声明之外定义时若使其成为内联函数,需加 inline限定符
在类中创建常量用作数组长度等用途直接声明行不通,因为类只描述对象的形式,并没有创建对象,因此创建对象前,没有用于存储的空间。解决方法是
1.声明一个枚举,作用域为整个类
class Bakery
{
private:
enum {Months = 12};
double costd[Months];
}; //这种方式声明枚举并不会创建类数据成员。即所有对象中都不包括枚举
2.使用关键字static,该变量将与其它静态变量储存在一起,而不在任何一个对象中,被所有此类的对象共享,C++98中,只能使用这种技术声明值为整数或枚举的静态常量,不能存储double常量,C++11消除了这种限制
作用域内枚举(C++11) 也可用struct代替class
enum class egg {small,medium, large};
enum class t_shirt {small, medium, large, xlarge};
egg choice = egg::large; //使用
作用域内枚举不能隐式转换成整型,必要时可显式转换
作用域内枚举的底层类型为int, 语法enum class : short egg {...}; 提供了不同选择,也可指定常规枚举的底层类型
类的自动转换
当构造函数可以只接受一个参数时,赋值语句会调用构造函数生成临时变量然后再把该变量赋值
例. Stonewt myCat; //Stonewt为一个类,有构造函数Stonewt(double lbs);
myCat = 19.6;
与
Stonewt myCat = Stonewt(19.6); 等价
要关闭这种特征, 可在构造函数声明处加 explicit 关键字. explicit Stonewt(double lbs);
类的转换函数 添加到类声明中
operator typeName(); //typeName为基本类型,如int、double等。
无参数,无返回值,但仍要返回相应类型 (附.int转换为四舍五入)
C++98中 explicit 不能用于转换函数。 C++11可以,即让其必须显示转换
类的特殊成员函数
1.默认构造函数,如果没有定义构造函数
2.默认析构函数,如果没有定义
3.复制构造函数,如果没有定义,用于将一个对象复制到新创建的对象中,即用于初始化过程中,而不是常规赋值过程。
原型 Class_name(const Class_name &);
调用时间
String ditto(motto); //假设motto是String对象
String metoo = motto;
String also = String(motto);
String * ps = new String(motto);
生成对象副本时,如按值传递,返回对象
4.赋值运算符,如果没有定义
原型 Class_name & Class_name::operator=(const Class_name &);
自定义赋值运算符时应注意
由于目标对象可能引用以前分配的数据,应使用delete[]释放
应避免对象赋给自身,否则,给对象重新赋值前,释放操作可能删除对象内容
返回一个指向调用对象的引用
5.地址运算符,如果没有定义
(C++11) 移动构造函数
(C++11) 移动赋值运算符
静态类成员函数
函数声明前加static, 但定义前不加。不属于任何对象,没有this指针,只能使用静态数据成员
定位new分配的对象必须显式调用析构函数,
成员初始化列表
调用类的构造函数将导致程序首先给成员分配内存,再使用常规赋值方法将值存储到内存,因此, 对于const数据成员,必须在执行到构造函数体之前初始化。C++提供了成员初始化列表,只有构造函数可用
例. Queue::Queue(int qs) : qsize(qs),... //Queue为类,qsize为const数据成员,多个赋值逗号分隔
使用注意:
1.这种格式只能用于构造函数
2.必须用这种格式初始化非静态const数据成员 (至少在C++11之前是这样)
3.必须用这种格式初始化引用数据成员
派生类
派生类构造函数要点
1.首先创建基类对象
2.派生类构造函数应通过成员初始化列表将基类信息传递给基类构造函数
3.派生类构造函数应初始化派生类新增的数据成员
若派生类重新定义某方法,派生类调用时需加作用域解析运算符指明基类,否则将视为调用该派生类的函数
派生类与基类的关系
基类指针和引用可以在不进行显示类型转换的情况下指向派生类对象
但,基类指针或引用只能用于调用基类方法
不能将基类对象和地址赋给派生类引用和指针
virtual 方法
继承中如果没有virtual, 程序将根据引用类型或指针类型选择方法,如果使用了virtual 将根据引用或指针指向的对象的类型选择方法
抽象基类(ABC)
在类虚函数成员声明后加 = 0 可以把该函数变成纯虚函数,则类中可以不定义该函数,但也不能创建该类对象,只用作基类
在保护和私有继承中可以使用using声明(只使用成员名,无括号、特征标、返回类型)使基类的成员函数在继承类中可见(成为继承类的公有接口)
多重继承(MI)
应解决的问题
1.从不同基类继承同名的方法
2.从多个相关基类继承同一个类的多个实例
解决方式:
一种方法是使用类型转换转换成冲突类的派生类
另一种是继承此基类时用virtual 关键字使其成为虚基类(virtual与public次序无关),这样多重继承时只包含此基类的一个副本。
基类为虚时,为避免多条途径传递信息给基类构造函数,将忽略信息通过中间类自动传递给基类,编译器将使用基类的默认构造函数,如不希望则需显式调用所需的构造函数