zoukankan      html  css  js  c++  java
  • 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++函数指针具有不同类型
  • 相关阅读:
    MFC project for a non-Unicode character set is deprecated
    关于Visual Studio 2013 编译 multi-byte character set MFC程序出现 MSB8031 错误的解决办法
    字符串比较自实现
    各种语言里获取当前模块的方法:ABAP,ABSL,C,nodejs
    SAP CRM product attachment的document template功能
    ABAP, UI5和webpack的处理入口
    ABAP, Maven, CF App和Webpack的build
    json格式的字符串序列化和反序列化的一些高级用法
    SAP ABAP Netweaver容器化, 不可能完成的任务吗?
    UI Component in CRM WebUI and Hybris
  • 原文地址:https://www.cnblogs.com/zengyou/p/2195590.html
Copyright © 2011-2022 走看看