发布日期:2015-12-29 09:09 来源: 标签: 编程语言 C++教程 C++函数 C++静态成员函数
本章我们主要学习静态数据成员有哪些特点?C++中非静态成员函数及静态成员函数使用实例,下面我们就做一下具体讲解,希望大家多多支持中国站长网络学院。
      c++的两大特色是多态和模板。其中多态是通过继承和虚函数来实现的,其中虚函数是通过每个对象里面的虚表来实现的。如果这个对象的类有虚函数,那么这个类就有一张虚表,存的是每个虚函数的入口地址,而这个类的每个对象,都会有一个4字节的指针,指向这张虚表,这个就是虚指针。
      面向对象语言都是用反射,也就是对象把自己的地址作为参数,传入成员函数的this指针,通过this指针来确定数据的。
在c++里面是通过将函数名和函数的参数列表结合来区分不同的函数,同名但不同参数列表的函数,是不同的函数。例如void foo(int,int)在c里面编译器是用_foo来识别,在c++里面是用_foo_int_int来识别。
      那么A类的foo函数和B类的foo函数,如果参数列表一致,怎么区分它们呢?用A类的一个对象调用成员函数,这个成员函数用到成员变量,怎么知道是在用这个对象的数据呢?这个解释,就是this指针。A类的foo(int,int)函数,已经被编译器编译成_foo_A*_int_int,也就是说隐含已经加入了函数所属类的信息,调用A类对象a.foo的时候,已经在调用foo(const A * this,int,int)这个函数。这也解释了,为什么在成员函数内部,使用成员变量,有时候(并不是全部情况下都如此)前面加this和不加this没有区别,编译器已经把foo里面用到的成员变量,用this指针指向了。
      如果你在全局中,这样定义这样一个函数foo(const A * this,int,int)去模仿成员函数的调用,将不能编译,因为this是关键字,this指针已经成为了c++的机制,在类成员函数用this才做形参(foo(int this)或者foo(float this)),也是非法的。这样试图和编译器生成的函数的第一个参数this来一个重定义。
举个例子,下面一段代码:
class A  
{  
public:  
    void foo(){ cout << "A foo" << endl; }  
};  
class B  
{  
public:  
    void foo(){ cout << "B foo" << endl; }  
};
foo将编译成:
void foo(const A* this)( cout << "A foo" << endl; }  
void foo(const B* this)( cout << "B foo" << endl; }  
调用a.foo(),编译器将转换成foo(&a)
有趣的是,A* pa = NULL; pa->foo();也没有异常退出,因为没有通过this引用任何成员变量,这个时候不过this指针为NULL而已。
上面说的只是面向对象的非静态成员函数,如果说到类里面的静态成员函数,解释又是另外一个。
1、静态数据成员 
  特点:  
  A、内存分配:在程序的全局数据区分配。  
  B、初始化和定义:
     a、静态数据成员定义时要分配空间,所以不能在类声明中定义。
     b、为了避免在多个使用该类的源文件中,对其重复定义,所在,不能在类的头文件中定义。 
     c、静态数据成员因为程序一开始运行就必需存在,所以其初始化的最佳位置在类的内部实现。  
  C、特点  
    a、对相于   public,protected,private   关键字的影响它和普通数据成员一样,    
    b、因为其空间在全局数据区分配,属于所有本类的对象共享,所以,它不属于特定的类对象,在没产生类对象时其作用域就可见,即在没有产生类的实例时,我们就可以操作它。  
  D、访问形式  
    a、类对象名.静态数据成员名  
    b、类类型名:静态数据成员名  
  E、静态数据成员,主要用在类的所有实例都拥有的属性上。比如,对于一个存款类,帐号相对于每个实例都是不同的,但每个实例的利息是相同的。所以,应该把利息设为存款类的静态数据成员。这有两个好处,第一,不管定义多少个存款类对象,利息数据成员都共享分配在全局区的内存,所以节省存贮空间。第二,一旦利息需要改变时,只要改变一次,则所有存款类对象的利息全改变过来了,因为它们实际上是共用一个东西。
2、静态成员函数  
  特点:  
  A、静态成员函数与类相联系,不与类的对象相联系。  
  B、静态成员函数不能访问非静态数据成员。原因很简单,非静态数据成员属于特定的类实例。
  作用:  
    主要用于对静态数据成员的操作。  
  调用形式:  
    A、类对象名.静态成员函数名()  
    B、类类型名::   静态成员函数名()
上面是一段精辟的分析,但是他没有说道编译器是如何实现这个调用的。下面一段代码,将解释这个过程:
    #include <iostream>  
    using namespace std;  
      
    class A  
    {  
    public:  
        static int count;  
        void foo(){ cout << "A foo" << endl; }  // 如果这样声明和定义一个成员函数,将直接产生一个 foo(A& this) 类型的函数  
        static void goo(){ cout <</* this << */"A goo"<< endl; }  // 静态函数没有 this 指针  
        void too(){ cout << typeid(*this).name() << endl; }  
    };  
      
    int A::count = 0;  
      
    class B : public A  
    {  
    public:  
        // 如果静态函数只能通过域运算符来调用的话,那class在静态意义下就成了命名域的概念了  
        // 如果没有下面这个函数,A类的goo函数将会继承下来,说明作为类的命名空间,也可以继承  
        static void goo(){ cout << "B goo" << endl;}        // 一个问题,静态的成员函数,是怎么区分开的呢?  
    };  
      
    int main()  
    {  
        A a , *pa;  
        pa->goo();       // 静态也跟普通函数一样,没有多态效果  
        a.goo();        // 是否是直接翻译成 A::goo() 竟然说我没引用过 a !- -  
        // a.foo();     // this 是关键字,不能拿来作为一个全局函数的参数,在转成 foo(&a) 的时候,一定是调用 foo(A& this) 这个函数  
        // A::foo();        // 这个 foo 没有带参数,只能调用静态的,静态的就直接编译成类似全局函数的不带 this 参数的类型  
        A::goo();       // 这样调用是正确的,这说明它没有 this 指针作为形参  
        system("pause");  
        return 0;  
    }  
      编译运行,将产生一个警告,说对象a和指针pa从来没引用过!通过对象调用静态函数,已经通过类型识别,被编译器替换成A::goo(),这个是由编译器做的,所以替换之后a就只定义了,但是没用引用过。换句话,static的成员函数,只能通过域运算符来调用,无论你是用对象调用还是用指针调用。
      static的成员变量,也是如此,只能通过翻译成域运算符来调用。这样两者结合在一起,说明了“类其实除了可以定义变量,还有一个重要的作用就是它是个命名域,相当于std::cout这样。而且,这个命名域,还能继承下来。”
      还记得stl里面的迭代器吗?迭代器的类,就是为了不污染全局空间,把迭代器类声明在某个stl容器类里面。这个类里面的类,只能通过容器和域运算符才可见,有趣的是,这个类中类,也可以继承。
#include <iostream>  
using namespace std;  
class A  
{  
public:  
    class C{};                              // 类中类  
};  
  
class B : public A  
{  
};  
int main()  
{  
    B::C c;         // 除了父类,子类也可见  
    return 0;  
}

相关评论

专题信息
    C++是在C语言的基础上开发的一种面向对象编程语言,应用广泛。C++支持多种编程范式 --面向对象编程、泛型编程和过程化编程。最新正式标准C++于2014年8月18日公布。 其编程领域众广,常用于系统开发,引擎开发等应用领域,是至今为止最受广大程序员受用的最强大编程语言之一,支持类:类、封装、重载等特性! 本教程从基础讲解了C++语言,希望对大家有所帮助,望多多支持中国站长网络学院。