C++笔记(5)特殊工具与技术

5.1 命名空间

xxx.h

namespace space{

void func(void);

class space_class

{

};//空间的成员可以是声明或者定义.

} //不以分号结束.



namespace space{

void func(void)

{

}

int i = 0;

} /*可以不连续,空间是可累积的,可以分散在多个文件中.*/


或者可以如下定义func;

xxx.cc

void space::func(void)

{

}

使用::访问空间space成员或者使用using声明.

using namespace space; 或者using space::成员.


5.1.1 嵌套命名空间

 

namespace space

{

int i = 1;

namespace nested_space

{

int i = 0; //屏蔽space成员名字

int j= 0;

}

int b = j; /* error, 'j' : undeclared identifier不能直接使用nested_space成员,必须通过nested_space::i. */

int b = nested_space::j; //OK

}

int i = space::nested_space::I;

namespace nickname_space = space; //别名

namespace nested_nickname_space = space::nested_space;



5.1.2 未命名的命名空间

在定义时未命名, 未命名的命名空间的定义局部于特定文件,不跨越其他文件.

 1 namespace space{
2
3 namespace{
4
5 //只在包含该space中可见.
6
7 }
8
9 }
10
11 namespace space{
12
13 int i = 1;
14
15 namespace{
16
17 int i = 0; //error
18
19 int j= 0;
20
21 }
22
23 int a = i; /*error, 'i' : ambiguous symbol, 未命名空间的成员名字不可与外围空间相同. */
24
25 int b = j; //ok,未命名空间,所以直接访问.
26
27 }
28
29 int c = space::j; //访问未命名空间中的成员.



5.2 多重继承

class parent1: public grandfather1

{

}

class son: public parent2, public parent1
{

son(): parent1(), parent2() {…} //构造所有的基类,按照继承顺序

~ son() {…} //按照构造的逆顺序.

};

如果parent1和parent2都定义了func()而son未定义func(),则

son obj;

obj.func(); //ambiguous.

obj.parent1::func(); //ok

5.3 虚继承

 1 class grandfather 
2

3 {
4
5 grandfather){}
6
7 }
8
9 class patent1: public vitrual grandfather
10
11 /*virtual, 虚继承,对于给定虚基类grandfather,无论该类在派生层次中作为虚基类出现多少次,只继承一个共享的基类子对象,如果其他类继承patent1,patent2,派生类中只出现公共基类grandfather的一个副本.*/
12
13 {
14
15 patent1():grandfather(){}
16
17 };
18
19
20
21 class patent2: virtual public grandfather
22
23 {
24
25 patent2(): grandfather() {…}
26
27 };
28
29
30
31 class son: public patent1, public patent2
32
33 {
34
35 son(): grandfather(), //初始化虚基类
36
37 patent1(), //patent1中忽略grandfather的构造
38
39 patent2() //patent2中忽略grandfather的构造
40
41 /*构造函数的顺序是,虚基类按照继承顺序,之后非虚基类按照继承顺序,析构函数与构造函数相反.*/
42
43 {
44
45
46
47 }
48
49 };

5.4 优化内存分配


5.4.1 allocator

allocator类是一个模板,提供类型化的内存分配以及对象构造与撤销.

allocator<T> a; //可以构造T类型的对象

a.allocate(n); //非配原始的未构造内存以保存T类型的n个对象, 返回指向分配的空间第一个T的指针.

a.deallocate(p, n); //释放内存, 在名为pT*指针中包含的地址处保存T类型的n个对象.

a.construct(p, t); //T* P处创建一个对象, T的复制构造函数用t初始化该对象

a.destroy(p); //析构p所指向的T对象

uninitialized_copy(b, e, b2); /*将迭代器[b, e]范围元素复制到b2开始的未构造的原始内存中(是构造而不是赋值)*/

uninitialized_fill(b, e, t); /*标准库copy的特殊版本将[b, e]中元素初始化为t,使用的是复制构造函数.*/

uninitialized_fill_n(b, e, t, n); /*[b, e]中至多n个元素初始化为t,使用的是复制构造函数.*/


operator new & operator delete

string *ps = new string("hello"); /*new calls operator new to allocate space, then call construct, return point to new object*/

delete ps; /*delete calls descontruct, then call operator delete to deallocated space */



5.4.2 运行时类型识别(RTTI)

typeid: 返回type_info类,默认构造函数和复制构造函数为private,所以不能定义type_infor对象,只能通过typeid返回,具有 t1==t2, t1!=t2, t1.name() //返回c风格字符串, t1.before(t2) //如果t1出现在t2之前,返回true,befor强制的次序与编译器有关

typeid (*p); 如果p定义了至少一个虚函数,则在运行时计算类型,如果p为动态指针,p值为0,则typeid(*p)抛出一个bad_typeid异常,如果p无定义任何虚函数,则结果与p的值不相关,返回的是p的静态类型.

dynamic_cast: 将基类类型的指针或引用安全地转换为派生类型的指针或引用,如果转换到指针类型的dynamic_cast失败,返回0,如果转换到引用类型的dynamic_cast失败,则抛出一个bad_cast类型的异常.

dynamic_cast<derived *>(baseptr);

dynamic_cast<derived &>(baseobj);

5.5 嵌套类

5.5.1 独立于外围类

xxx.h

 1 template<class type> class myclass
2
3 {
4
5 private:
6
7 int m_i;
8
9 class nested_class
10
11 {
12
13 nested_class();
14
15 void func(const type &);
16
17 void func2()
18
19 {
20
21 int a = m_i; //可以直接使用外围类的成员.
22
23 }
24
25 };
26
27 };
28
29


xxx.cc

template<class type> outclass<type>::nested_class::nested_class()

{

}



5.5.2 在外围类外部定义嵌套类

 xxx.h

 1 template<class type> class outclass
2
3 {
4
5 private:
6
7 class nested_class;
8
9 };
10
11 template<class type> class outclass<type>::nested_class
12
13 {
14
15 public:
16
17 nested_class();
18
19 void func(const type &);
20
21 };

xxx.cc

1 template<class type> outclass<type>::nested_class::nested_class()
2
3 {
4
5 }

5.6 union


当前只有一个成员有值,其他成员变成未定义的.

默认情况下,表现类似struct,但是不能作为基类,成员函数不能为虚函数,不能具有静态数据成员和引用成员,不能具有定义了构造函数,析构函数或赋值构造函数的类类型的成员.

 1 union unionname
2
3 {
4
5 myclass obj; //error
6
7 static int is; //error
8
9 int &rfi; //error
10
11 int i; //ok
12
13 char c; //ok
14
15 myclass * pobj; //ok
16
17 };
18
19 unionname obj = {1};
20
21 obj.c = 'a';


5.6.1 嵌套联合

 1 class outclass 
2
3 {
4
5 union unionname
6
7 {
8
9 int i;
10
11 } unionval;
12
13 };
14
15 outclass obj;
16
17 obj. unionval.i;

5.6.2 匿名联合

 1 class outclass
2
3 {
4
5 //如果外围定义与union相同的成员名,屏蔽union成员.
6
7 union
8
9 {
10
11 int i; //不能有私有成员和受保护成员,也不能有成员函数.
12
13 };
14
15 };
16
17 outclass obj;
18
19 obj.i;

5.7 局部类

局部类:在函数体内定义的类.所有成员必须定义在类定义体内部,所以不允许声明static数据成员.

 1 void func(void)
2
3 {
4
5 class localclass
6
7 {
8
9 public:
10
11 localclass(): m_i(0) {}
12
13 int get()
14
15 {
16
17 return m_i;
18
19 }
20
21 private:
22
23 int m_i;
24
25 };
26
27 }

5.8 链接指示- extern “c”


C++程序有时候需要使用其他语言,使用链接指示只出任意非C++函数所用的语言.

 1 extern "c" size_t strlen(const char *); //C不支持重载,所以不可链接多个相同名字函数.
2
3 extern "c"  //链接指示必须放在全局域中.
4
5 {
6
7 int strcmp(const char*, const char*);
8
9 size_t strlen(const char*);
10
11 #include <string.h>
12
13 }

通过对函数定义使用链接指示,可以将函数导入到其他语言.

1 extern "c" double func(void) {//func函数定义体}
2
3 extern "c" void (*pf1)(int);
4
5 void(*pf2)(int);
6
7 pf2 = pf1; //error, 'c' : illegal linkage specification,C函数指针和C++函数指针具有不同类型
原文地址:https://www.cnblogs.com/zengyou/p/2195590.html