第11课 - 类的静态成员

第11课 - 类的静态成员

    一.类的普通成员的回顾

        1.1 通过对象名能够访问public成员变量

        1.2 每个对象都可以有只属于自己的成员变量

        1.3 成员对象不能在对象之间共享                                                                             

        

        1.4 新的需求:

            a.统计类在程序运行期间有多少个对象同时存在

            b.保证程序的安全性(不能使用全局变量),并随时可以获取对象数目

                如果使用普通的成员变量,对象存在那么成员变量存在
                对象销毁的时候成员变量也会被销毁,因此成员变量没有能力来统计对象的个数的。
    

    二.类的静态成员(属于类)

        2.1 类的静态成员特点

            2.1.1  在C++中可以定义静态成员变量和静态成员函数

            2.1.2  静态成员属于整个类所有,不需要依赖任何对象

            2.1.3  可以通过类名直接访问public静态成员

            2.1.4  可以通过对象名访问public静态成员

            2.1.5  静态成员函数可以直接访问静态成员变量

        

        2.2 静态成员变量的定义

            2.2.1 在定义是直接通过static关键字修饰

            2.2.2 静态成员变量不依赖于任何对象,需要在类外单独分配空间,即存在于全局数据区

            2.2.3 语法规则: Type ClassName::VarName;

    
        

        2.3 静态函数的定义

            2.3.1 在定义时直接通过static关键字修饰

            2.3.2 其余部分与普通成员函数定义相同        

 Source Example 2:
             #include <iostream>

            /* run this program using the console pauser or add your own getch, system("pause") or input loop */

            class Test{
                private:
                    static int i;
                public:
                    static int getI(void)
                    {
                        return i;
                    }
                    
                    static void setI(int a)
                    {
                        i = a;
                    }
                    
                    void print()
                    {
                         printf ("i = %d\n", i);
                    }
            };
            /* 必须为i分配空间,在全局数据区 */
            int Test :: i = 0;

            int main(int argc, char** argv) {
                
                /* 下面这句会出错,因为即使i是静态变量也会被private限制 */
                //Test::i = 5;
                
                /* 静态函数不依赖于对象,直接根据类就可以调用 */
                Test::setI(5);
                
                int x = Test::getI();
                printf ("x = %d\n", x);
                
                /* 执行下面这句会出错,因为print不是静态函数,需要依赖于对象才可以调用 */
                //Test::print();
                return 0;
            }


       注意:静态成员变量属于类,因此也属于对象,可以使用对象修改静态成员变量的值。
        

 

        2.4 从命名空间的角度看

 

            2.4.1 类的静态成员只是类这个命名空间中的全局变量和全局函数

            2.4.2 不同之处是,类可以对静态成员进行访问权限的限制,而命名空间不行

        

        2.5 从面向对象的角度看

            2.5.1 类的静态成员属于类概念本身

            2.5.2 类的所有对象共享相同的静态成员

            

    三.静态成员的应用(统计某个类的对象数目)

      

  #include <iostream>

        /* run this program using the console pauser or add your own getch, system("pause") or input loop */

        class Test{
            private:
                static int iCount;
            public:
                static int GetCount()
                {
                    return iCount;
                }
                
                Test()
                {
                    iCount++;
                }
                
                ~Test()
                {
                    iCount--;
                }
                
        };

        /* 如果没有赋初始值,默认值是0,因为放在全局数据区 */
        int Test::iCount = 0;

        void run()
        {
            Test ta[100];
            
            /* 输出结果为100 */
            printf ("Number of object = %d\n", Test :: GetCount());
        }

        int main(int argc, char** argv) {
            
            run();
            
            /* 输出结果为0 */
            printf ("Number of object = %d\n", Test :: GetCount());
            return 0;
        }  

    四.静态成员函数和普通成员函数的区别

        4.1 C++类对象中的成员变量和成员函数时分开存储的

            4.1.1 成员变量

                普通成员变量:存储于对象中,与struct变量有相同的内存布局和字节对齐方式

              静态成员变量:存储于全局数据区中

            4.1.2 成员函数

                存储于代码段中

              程序依然由数据段(计算机数据)和代码段(可执行代码)构成

        

Source Example 4.1:
            #include <iostream>

            /* run this program using the console pauser or add your own getch, system("pause") or input loop */

            /* struct与class的区别只有访问权限不同,class默认是private,struct默认是public */

            struct C1 {
                int i;
                int j;
                short k;
                short l;
            };

            class C2 {
                int i;
                int j;
                short k;
                short l;
            };

            class C3 {
                int i;
                int j;
                short k;
                short l;
                
                /* 静态成员函数,不占用class的空间,存储在全局数据区 */
                static int x;
                
                public:
                    /* 函数存储与代码段中 */
                    C3()
                    {
                    }
                    
                    void print()
                    {
                    }
            };

            /* 为静态x成员分配空间 */
            int C3::x = 0;
            
            int main(int argc, char** argv) {
                
                C1 c1;
                C2 c2;
                C3 c3;
                
                /*    输出结果为:
                    sizeof (C1) = 12
                    sizeof (C2) = 12
                    sizeof (C3) = 12
                 */
                
                printf ("sizeof (C1) = %d\n",sizeof (c1));
                printf ("sizeof (C2) = %d\n",sizeof (c2));
                printf ("sizeof (C3) = %d\n",sizeof (c3)) ;
                
                
                return 0;
            }
            
                                    /* C++编译器将程序转换为面相对象内部处理 */
        Source Example 4.2 :
            /* C++代码 */                                                            /* 编译器内部处理方式 */        
            class Test                                                                struct class
            {                                                                        {
                                                                                        int i;
            private:                                                                }
                    int i;        
                public:                                                                /* 一个pThis指针指向当前创建的对象 */
                    Test(int x)                                                        void Test_initialize(Test* pThis, int x)
                    {                                                                {
                        i = x;                                                            pThis->i = x;
                    }                                                                }
                                                                                    
                    
                    int getI()                                                        int Test_getI(Test* pThis)
                    {                                                                {
                        return i;                                                        return pThis->i;
                    }                                                                }
                    
                    static void Print()                                                void Test_Print()
                    {                                                                {
                        printf ("This is a class Test!\n");                                printf("This is a class Test!\n");
                    }                                                                }
            }
            
            int main()                                                                int main()                                                        
            {                                                                        {
                Test a(10);                                                                Test a;
                                                                                        Test_initialize(&a, 10);        
                a.getI();                                                                Test_getI(&a);
                                                                                        /* 该函数是静态函数,不属于对象,因此不需要pThis指针 */
                Test::Print();                                                            Test_Print();
                return 0;                                                                return 0;
            }                                                                        }

 

        因此得出结论(静态成员函数与普通成员函数的区别)

 

            a.静态成员函数不包含指向具体对象的指针

            b.普通成员函数包含一个指向具体对象的指针

                C++中类的普通成员函数都隐士包含一个指向当前对象的this指针。

                
        再次验证this指针:
            

/* 静态成员与非静态成员区别 */
            Source Example 4.3:
                #include <iostream>

            class Test {
            private:
                int i;
                int j;
                int k;
                /* 静态成员函数,不占用class的空间,存储在全局数据区 */
                static int x;
                
            public:
                    Test(int i, int j, int k)
                    {
                        /*  如下方式赋值会造成作用域重叠,都是用参数的i,j,k,因此类中的i,j,k为随机数
                         *  i = i;
                         *  j = j;
                         *  k = k;
                         *  this指针指向当前对象
                         */
                        this->i = i;
                        this->j = j;
                        this->k = k;
                    }
                    
                    void print()
                    {
                        /* t1的this指针地址为22fe50与&t1相同,说明了this指针指向了当前对象 */
                        printf ("this pointer address = %08x\n", this);
                        /* t1,t2的&x地址相同,证明了静态成员存储与全局数据区中 */
                        printf ("&x = %08x, x= %d\n", &x, x);    
                        printf ("&i = %08x, i = %d\n", &i, i);
                        printf ("&j = %08x, j = %d\n", &j, j);
                        printf ("&k = %08x, k = %d\n", &k, k);
                    }
                    
                    /* 加上如下代码编译出错,因为静态成员函数没有this指针,从上一个例子中C++内部处理方式也可以看出。
                     * static void Print()
                      * {
                     *        printf ("this pointer address = %08x\n", this);
                     * }
                     */
            };

            /* 为静态x成员分配空间 */
            int Test::x = 0;
            
            int main(int argc, char** argv) {
                
                Test t1(1,2,3);
                Test t2(4,5,6);
                
                printf ("&t1 = %08x\n", &t1);
                t1.print();
                printf ("&t2 = %08x\n", &t2);
                t2.print();

                
                return 0;
            }

            输出结果如下:

    

五.小结

    5.1 C++类中可以包含属于类概念的静态成员

    5.2 静态成员变量在全局数据区分配空间

    5.3 静态成员函数不包含隐藏的this指针

    5.4 通过类名可以直接访问静态成员

    5.5 通过对象名也可以访问静态成员,所有的对象可以共享一个同一个类的静态成员

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值