qq_23876277
2016-11-14 02:55
采纳率: 100%
浏览 2.3k

C++中静态成员变量和静态成员函数的定义区别

楼主小白,请教一下大家,为什么C++中,静态成员函数可以在类中定义。

 class A 
{
    public:
        static void func() 
        {
            cout << "test" << endl;
        }
};

而静态成员变量却不能在类里面定义

 class A 
{
        public:
                static int a = 1;   \\error 
};

为什么静态成员函数和静态成员变量会有这两种差异?小弟在此先谢谢啦

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

7条回答 默认 最新

  • NavNet 2016-11-15 01:23
    已采纳

    楼上说的我觉得有一定的道理, 但是我觉得从本质来讲,之所以成员函数可以直接定义,而成员变量不能直接定义主要是因为内存分配的问题
    成员函数不需要考虑预分配内存的问题,可以直接在运行时分配堆栈内存,因此可以直接在编译阶段编译到类中,运行调用时动态创建必要的堆栈。而静态成员变量,是类的所有对象共有的,必须在编译时就完成内存分配到静态区而不在类中。所以静态成员变量不能放在内中,而静态成员变量可以放到类中

    点赞 评论
  • 赵腾王 2016-11-14 03:03

    静态成员属于类而不属于对象。静态变量,需要在类外部初始化。

    点赞 评论
  • 小乌龟慢慢爬xhy 2016-11-14 04:02

    在c++中静态函数和静态成员都属于类,存在于内存中,而普通成员实例化后才能分配内存。
    c++中静态成员变量要在类外部再定义,否则产生link2001错误,解释如下:
    1. 在类中,只是声明了静态变量,并没有定义。
    2. 声明只是表明了变量的数据类型和属性,并不分配内存;定义则是需要分配内存的。
    注意:如果在类里面这么写int a; 那么是既声明了变量,也定义了变量,两者合在一起了。
    3. 静态成员是“类级别”的,也就是它和类的地位等同,而普通成员是“对象(实例)级别”的。
    类级别的成员,先于该类任何对象的存在而存在,它被该类所有的对象共享。
    4. 现在,咱们假定要实例化该类的一个对象,那么会发生什么事情呢?
    静态成员肯定要出现在这个对象里面的,对吧?这时候才去定义那个静态成员吗?这显然是不合适的。
    因为,比如有另外一个线程也要创建该类的对象,那么也要按照这个方式去定义那个静态成员。
    这会产生两种可能的情况:
    A. 重复定义;
    B. 就算不产生重复定义的情况,也会产生竞争,从而造成死锁的问题,以至于对象无法创建。
    很显然,编译器不能这么干。那么很合理的解决办法,就是事先在类的外部把它定义好,然后再供所有的对象共享。
    当然这样做,还是有可能产生线程安全的问题,但不管怎么说对象是创建好了,而这种线程安全问题,可以在编程中予以解决。

    点赞 评论
  • altitude-privilege-L 2016-11-14 04:57

    类的静态数据成员在 类中只能声明,定义和初始化必须在类外,你可以把整个程序看作充满类的容器,而静态成员变量是一个特殊的类,你要使用这个类就必须先存在这个类,
    你调用一个不存在的类当然会报错,在加载过程中首先会查找定义,再调用。

    点赞 评论
  • ipqtjmqj 2016-11-14 05:56

    因为函数可以内联(inline),在类内定义的函数默认是内联的,而变量没有内联。
    内联的目的是减小函数调用时的开销,变量没有调用,只需寻址,所以变量没有内联的。
    所以静态变量按照声明与定义分离的原则,必须在类外定义。
    内联函数需定义在头文件中,这样编译时就获取了函数的实现,从而编译时“内联”,而非内联函数在编译时只是知道有这么一个函数,编译通过链接时不一定通过。

    点赞 评论
  • qq_23876277 2016-11-16 05:53

    图片说明
    感谢你清楚我了想问的问题,如果在你说的那些知识的前提下,从你说的逻辑来看确实能够解释。不过我对你的这句话“对于方法而言不管是否静态都是放在代码区被所有对象公用”进行了考证了,写了以下程序,结果应该是你的这个观点不成立的。从程序结果来看应该是静态成员函数和静态成员都在内存中的静态\全局存储区吧。

     #include<iostream>
    #include<string.h>
    
    #include"test.h"
    using namespace std;
    
    class Test 
    {
        public:
            static int a;
            void func1() 
            {
                cout << this << endl;
            };
            static void func2() 
            {
            };
    
    
    
    };
     int Test::a=1;
    
    
    int main() {
        Test test;
        cout << &(test.a)<<endl;
        test.func1();
        cout << test.func2 << endl;
        system("pause");
        return 0;
    }
    
    点赞 评论
  • 想要飞的鱼儿 2019-08-12 14:18

    对于方法而言不管是否静态都是放在代码区被所有对象公用。

    #include<iostream>
    #include<string.h>
    
    using namespace std;
    
    class Test 
    {
        public:
            static int a;
            void func1() 
            {
                cout << this << endl;
            };
            static void func2() 
            {
            };
    
    
    
    };
    int Test::a=1;
    
    int main() {
        Test test;
        Test test2;
        test.func1();
        cout << &(test.a)<<endl;
        printf( "00%X\n", &Test::func1);
        cout << &test.func2 << endl;
        cout << &test2.func2 << endl;
        system("pause");
        return 0;
    }
    

    图片说明
    https://www.cnblogs.com/skytcat/p/11339793.html

    点赞 评论

相关推荐 更多相似问题