_Lulixue_ 2014-10-08 08:42 采纳率: 0%
浏览 2380
已采纳

C++私有内部类静态变量未进行类体外定义

以下为Singleton.h:

class HungerSingleton
{
private:

    class CGarbo  // 用于析构s_pInstance
    {
    public:
            ~CGarbo()
        {
            if(HungerSingleton::s_pInstance)
                delete HungerSingleton::s_pInstance;
        }
    };
    static CGarbo Garbo;
    static HungerSingleton *s_pInstance;
public:
    static HungerSingleton * GetInstance()
    {
        return s_pInstance;
    }
};

下为Singleton.cpp:
HungerSingleton* HungerSingleton::s_pInstance = new HungerSingleton;

测试函数:
void TestSingleton()
{
HungerSingleton *phgl = HungerSingleton::GetInstance();
}


为什么Garbo作为静态变量没有在类外部定义,而程序却没有报错呢?

  • 写回答

1条回答 默认 最新

  • 「已注销」 2014-10-08 16:09
    关注

    测试环境:VS2013的优化已禁用 (/Od),警告等级 4 (/W4)

    因为你的 static CGarbo Garbo;的 CGarbo类里面并没有数据成员,CGarbo是一个空类,所以sizeof(CGarbo)==1; 如果CGarbo的public(为了测试方便)加上一个数据成员char c,另外在HungerSingleton类的GetInstance()加上cout << Garbo.c << "\n"; 那么sizeof(CGarbo)还是==1; 但是在我加上char c以后,你的CGarbo有了数据成员,此时执行我给你的新改装类,则会满满的报错,error LINK2001(不解释),因为对于无数据成员的类,编译器会产生于有数据成员的类不同的目标代码,所以加上char c以后,类的目标码不同,而且编译器知道你用了未初始化的Garbo.c,如果你不在外部显示提供初始化,是通不过的。但是你去掉cout << Garbo.c << "\n";这句,可以通过,因为编译器在编译的时候发现你自始至终没用过Garbo的.c,故不影响链接,不会报错。

    另外补充一句,现在的编译器很智能,即使在10年前,Silicon Graphics的N32和N64编译器已经能自动为所有型别提供适当的type_traits的特化版本,进行STL优化。10年过去了,编译器技术突飞猛进,如果你懂汇编,去调整编译器的优化级别,反复观察汇编码,你就知道编译器给你优化了什么了。(我用的的/Od)

    最有给你我改的代码,注释部分你好好看看,如果你去掉cout << Garbo.c << "\n";的注释,就会报错。此时你再去掉首位的注释去初始化,问题就OK了。

    #include
    using std::cout;

    class HungerSingleton
    {
    private:

    class CGarbo  // 用于析构s_pInstance
    {
    public:
        //CGarbo(char c) :c(c){ }
        char c;
        ~CGarbo()
        {
            if (HungerSingleton::s_pInstance)
                delete HungerSingleton::s_pInstance;
        }
    };
    static CGarbo Garbo;
    static HungerSingleton *s_pInstance;
    

    public:
    static HungerSingleton* GetInstance()
    {
    //cout << Garbo.c << "\n";
    cout << sizeof(CGarbo) << "\n";
    return s_pInstance;
    }
    };
    HungerSingleton* HungerSingleton::s_pInstance = new HungerSingleton;
    //HungerSingleton::CGarbo HungerSingleton::Garbo('a');

    void TestSingleton()
    {
    HungerSingleton *phgl = HungerSingleton::GetInstance();
    }

    int main()
    {
    TestSingleton();

    return 0;
    

    }

    你的问题非常好,我学习了。祝你事业进步,生活快乐!

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 应该如何判断含间隙的曲柄摇杆机构,轴与轴承是否发生了碰撞?
  • ¥15 vue3+express部署到nginx
  • ¥20 搭建pt1000三线制高精度测温电路
  • ¥15 使用Jdk8自带的算法,和Jdk11自带的加密结果会一样吗,不一样的话有什么解决方案,Jdk不能升级的情况
  • ¥15 画两个图 python或R
  • ¥15 在线请求openmv与pixhawk 实现实时目标跟踪的具体通讯方法
  • ¥15 八路抢答器设计出现故障
  • ¥15 opencv 无法读取视频
  • ¥15 按键修改电子时钟,C51单片机
  • ¥60 Java中实现如何实现张量类,并用于图像处理(不运用其他科学计算库和图像处理库))