C++语言中级(二)

2014-11-24 09:57:49 · 作者: · 浏览: 6
. 类型兼容规则: 切割 或者 假切割。
38. 在公有继承中:
派生类的对象可以替代基类的对象;
派生类的对象可以被赋值给基类的对象;
派生类的对象可以初始化基类的引用;
指向基类的指针可以指向派生类对象。
39. 二义性
(1). 同名二义(同名隐藏规则): 派生类与基类成员同名时,派生类成员将屏蔽基类中的成员;若要访问基类,需要用“类名::”;据继承方式不能区分二义性。
(2). 路径二义(多继承中的多层共组): 解决方式: 虚基类,class B: virtual public A。
40. 最远派生规则:
虚基类的成员是由最远派生类的构造函数通过调用虚基类的构造函数进行初始化的。
41. 虚基类的构造函数调用规则:
(1).产生对象的派生类首先调用虚基类的构造函数;
(2).然后安装继承次序调用直接基类的构造函数;
(3).如果有包含的对象,再按照声明次序调用所包含对象类的构造函数;
(4).最后才执行函数体,普通类型数据成员被赋予初值。
(5).多继承时,访问权限就低不就高,即以最低访问权限为准。
42. 局部类与内嵌类:
局部类: 函数体内定义的类,只有在该函数内用;必须采用隐含内联的方式定义,不能含有静态数据成员,常采用匿名类的方式. 典型应用是STL中的迭代器
内嵌类: 类中定义一个新类,class B { class A {…} } , 最外层实现 B::A::fun() {…}
43. 多态的类型:
(1). 类型转换多态: 四个cast;
(2). 重载: 运算符重载和函数重载 ---> 静态多态;
(3). 虚函数--->动态多态;
(3). 模板: 函数模板和类模板;
44. 运算符重载:
(1). 运算符重载的两种形式: 重载为成员函数或者友元函数;重载不能为类属性即不能为静态,不能改变优先级、结合性、操作数个数,只能重载已有运算符;
(2). 下列运算符不能重载: . .* :: : sizeof typeid # || && ,(逗号) 四个cast;
(3). 重载前++一定返回引用,重载后++一定返回对象
Clock & operator ++(); //前++,返回引用是为了连续运算,如++++C
Clock operator ++(int); //后++,参数仅识别重载,后++返回加之前的临时对象,而非*this
(4). 对象赋值出现赋值运算符连锁调用 X & X::operator = (X x);
重载函数调用运算符() X(arg1,arg2) ---> X.operator()(arg1,arg2)
下标运算符重载[] X[Y] ---> X.operator[](Y)
(5). 重载为友元判断标准: Complex C1; 5+C1---> 5.operator+(C1);//错误
45. 运算符重载的设计原则:
(1).全部的单目运算符建议设计为成员函数,重载为成员函数参数会比原来少一个;
(2).全部双面运算符建议设计为友元函数;
(3). = () [] -> * 必须重载为成员函数;
(4). >> <<必须是友元函数;
(5).虚函数建议设计为成员函数;
(6).若允许链式运算,应返回本对象引用;
(7).若定义了+ - * / %之一,千万别忘了定义“=”;
(8).所有的赋值(如+=、<<=、|、&、=)建议为成员函数;
46. 隐式类型转换规则:
(1). 算术表达式中,短服从长,简单服从复杂;
(2). 赋值表达式中,右服从左;
(3). 三目运算符中, = 取表达式2和3中最大的那个;
(4). 函数调用形实结合,实参服从形参;
(5). 函数返回与函数类型不一致,返回值服从返回类型.
47. 类型转换函数:
(1). 外--->内:构造函数 如,T t(5); 5--->T t=5; --->t=T(5);
构造函数承担了从外向内的类型转换,只用于带参构造函数;
explict关闭构造函数类型转换功能;
(2). 内--->外:operator 类型名()
不写返回类型,不写参数,必须有return语句,可以被继承,可以是虚函数,类里可以有多个,该函数应该是类的非静态成员函数,为const更好。
48. (1).虚函数只能由指针或者引用调用,可以为private.
(2).**vptr 对象属性; vtable为类属性,登记virtual函数;
(3).动态多态的前提: 公有继承,基类virtual,派生类重写,用指针或引用调派生类对象;
(4).子类虚函数表项至少和父类相等,包括虚析构;
(5).”重写”返回类型可允许”类型兼容”;
(6).父类void fun() const和子类的void fun()是”隐藏”关系,因为参数不同;
(7).vptr也服从对齐原则,一个派生类有多个父类时,该对象会有多个vptr指向各自的vtable,多层共组则会合并;
49. 纯虚函数 virtual 类型 函数名(参数表) = 0;
纯虚函数也可以有函数体,其函数体可被子类重写中调用,”=0”本质上使vtable对应位置为NULL;
当类中包含至少一个虚函数的时候才声明虚析构函数,若想使一个类成为抽象类但刚好又没有任何虚函数,可以在想要成为抽象类的类中声明一个纯虚析构函数 virtual ~function() = 0;
50. 抽象类只能用于产生指针和引用,不能产生对象,只能当做基类,不能作为转换目标、参数、返回值。
51. 命名空间(逻辑概念):
(1).Namespace NS{…},在命名空间外访问,要使用前缀。
(2).匿名空间: namespace {…} 本文件域内无限制使用,但别的文件不可使用,相当于C语言”全局静态”; 头文件不编译,一个编译单元只可以有一个匿名空间,VC中一个.cpp是一个编译单元。
52. 命名空间的使用方法:
(1). NS::File obj; NS::Fun();
凡用就要加,最小开放度 ---> 单个一次性开放;
(2). using NS::File; ---> 单个一劳永逸开放;
(3). Using namespace std; ---> 全面开发,可能产生”名字冲突”,同名覆盖,外来服从内层。解决二义性用”命名空间::”区分。
(4). 优先级:开放程度越小,优先级越高。
(5). 名空间可用别名: namespace 新名 = 旧名;
(6). 所有不带.h的头文件都在std中;所有带.h的头文件共18个,都是全局的;使用了using namespace std时不得再使用标准库中的.h头文件,因为它们不在std中;但自己定义的头文件可以使用.h。
53. RTTI(run-time type Identification)动态类型识别:
类型转换:
C风格: (int)… int(…)
C++风格: 四个cast
(1).const_cast (object) 去掉常属性
String const B(“Hello World”);
String &b = const_cast (B);
(2). Static_cast (object) 除以上3种cast以外,所有的都能转换,类似于C语言的”()”.
Double d = 12.34; Int a = static_cast (d);
(3).reinterpret_cast (object) 用于转换指针,转换不安全,尽量少用。
Double d = 3.14; int *p = reinterpret_cast (&d);
(4).dynamic_cast (object) 运行时转换符
a.能将派生类的指针或引用转换为基类;
b.能将基类的指针或引用转换为派生类类型,不可用于对象;转指针失败返回NULL,转引用失败抛出异常std::bad_cast;
dynamic_cast