c++中的命名控制

来源:互联网 发布:人脸识别原理及算法 编辑:程序博客网 时间:2024/04/28 00:01
    C中的static关键字在人们发明"重载"这个概念之前实际上已经被重载了,而C++则为static增添了新的含义。

    在C和C++中,static都具备两个基本语意,不幸的是,两者经常混杂在一起。

    1.在固定地址空间分配内存,而不是每次函数调用时在栈上分配空间。这里static的意味是静态存储(static storage)。
    2.只对一个特定的转换单元(translation unit)可见。这里static的意味是内部链接(internal linkage)。


函数中的static变量


    若程序员不为static局部变量提供初始化值,编译器会保证该对象被初始化为0(对于内置类型)。

函数中的static对象

   
    默认初始化为0只对内置类型有意义,对于static类对象,必须由构造函数完成初始化。

静态对象的析构

    静态对象(不仅限于局部静态变量)在程序从main()函数推出时被自动调用析构函数。
    如果调用标准库函数abort()结束程序的话,静态对象的析构函数是不会被自动调用的。

    需要理解的是,只有已经被创建的对象才被析构。具体的说,一个包含局部静态对象的函数若从未被调用过的话,该类对象的析构函数自然不会在推出main()时被调用,因为该对象根本还不曾存在过!

链接控制


    使用内部链接(internal linkage)的优点之一在于可以在将标识符的定义放置在头文件中,而不用担心链接时会出现名字冲突的问题。

    C++中通常放置于头文件中的名字定义,如const,默认具有internal linkage属性。

    当用于局部变量时,static不再具有可见性的含义,而只是改变变量的存储方式。

名字空间


    namespace关键字的唯一目的是创建名字空间

    创建名字空间时需要注意的:  

    1。名字空间的定义只能出现在全局范围,或者是在另一个名字空间的内部
    2。名字空间定义的结尾处不需要加分号。
    3。一个名字空间的定义可在多个文件中完成。
    4。一个名字空间可以定义为另一个名字空间的alias。


匿名名字空间


    匿名名字空间中的名字在其所在的转换单元中自动可见,不用加限定符。

    编译器保证每个转换单元(translation unit)中最多只有一个匿名名字空间。

    匿名名字空间中的名字虽然对于外部TU是不可见的,但其链接属性仍是external linkage。

    C++废弃了使用static来设置internal linkage的方法,而推荐使用匿名名字空间。


友元与名字空间

    若在类定义中声明友元的话,该友元自动被插入类所属的名字空间
例如:

    namespace Me {
    class Us {
    //...
    friend void you();
    };
    }

    现在函数you()是名字空间Me的一员了。

使用名字空间

    可以通过三种方式来使用某个名字空间内的名字

    1。显式使用范围限定符::。
    2。使用using directive,将某个名字空间内的名字全部引入当前名字空间。
    3。使用using declaration,一次引入一个名字。

    using和namespace关键字一起使用时被称为using directive。

    using declaration被视为在当前范围内的声明,而using directive被视为对当前范围全局性的声明;因此,using declaration可能会覆盖using  directive引入的名字。

    using declaration只是引入了名字,并没有包含类型信息;
      
    using directive的有效性只到那个文件的编译器为止。
   
    实际上,using directive 通常出现在.cpp文件而不是在头文件中,因为这样做会污染全局名字空间。


C++中的静态成员


    类中的静态成员必须在类定义之外被定义(但是在类定义中同样要进行声明),并且只允许被定义一次,因此,这样的静态成员的定义一般放在类的实现部分(.cpp),而不是定义部分(.h)。

    初始化:对于static const的整型变量可以在类中进行定义,对所有其它情况,必须在类外完成定义。

    局部类不允许拥有静态成员变量。

    静态成员函数:静态成员函数只能访问静态成员变量,无法访问非静态成员变量,也不发调用非静态成员函数。这是因为静态成员函数在调用时没有this指针被传递

静态成员函数的地址可用普通函数指针储存,而普通成员函数地址需要用 类成员函数指针来储存。举例如下:
class base{
static int func1();
int func2();
};

int (*pf1)()=&base::func1;//普通的函数指针
int (base::*pf2)()=&base::func2;//成员函数指针


静态成员函数不可以调用类的非静态成员。因为静态成员函数不含this指针。

静态成员函数不可以同时声明为 virtual、const、volatile函数。举例如下:
class base{
virtual static void func1();//错误
static void func2() const;//错误
static void func3() volatile;//错误
};


最后要说的一点是,静态成员是可以独立访问的,也就是说,无须创建任何对象实例就可以访问。

0 0
原创粉丝点击