You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

单例继承疑问:调用派生类构造时创建的是哪个对象?

单例继承场景下的实例类型疑问

我创建了两个类——基类和派生类,其中基类是Singleton(单例)。当调用派生类的构造函数时,作为静态实例被创建的是哪个对象?是基类对象还是派生类对象,原因是什么?

代码示例

#include <iostream>
class Singleton {
protected:
    static Singleton* instance;
    Singleton() {}
public:
    static Singleton* getInstance() {
        if (!instance) {
            instance = new Singleton();
        }
        return instance;
    }
};
Singleton* Singleton::instance= nullptr;;

class DerivedSingleton : public Singleton {
public:
int x;
    static DerivedSingleton* getInstance() {
        if (!instance) {
            instance = new DerivedSingleton();
        }
        return (DerivedSingleton*)instance;
    }
};
int main(){
    Singleton *instance = DerivedSingleton::getInstance();
    std::cout << sizeof(DerivedSingleton) << std::endl;
    std::cout << sizeof(*instance) << std::endl;
    std::cout << sizeof(Singleton) << std::endl;
}

输出结果

4
1
1

我尝试打印了大小值,但无法理解为何创建的是基类对象。


解答

首先明确:实际创建的是DerivedSingleton对象,不是基类对象,你看到的sizeof结果是编译期特性导致的误解,具体原因如下:

  • 静态成员的共享性:基类Singleton的静态成员instance是所有派生类共享的。第一次调用DerivedSingleton::getInstance()时,instance为空,所以会执行new DerivedSingleton(),此时分配的是派生类的内存(包含基类部分和int x成员,所以sizeof(DerivedSingleton)是4)。
  • sizeof的编译期计算:sizeof(*instance)的结果由instance的静态类型(Singleton*)决定,这是编译阶段就确定的。空类Singleton的大小是1(C++标准要求每个对象必须有唯一地址,空类会被分配1字节的占位空间),所以不管instance运行时实际指向什么对象,sizeof(*instance)都会返回1。
  • 验证实际对象类型:如果在main函数里把指针转换为派生类类型,就能正常访问派生类的成员,证明实际是派生类对象:
    DerivedSingleton* d_inst = static_cast<DerivedSingleton*>(instance);
    d_inst->x = 100;
    std::cout << d_inst->x << std::endl; // 输出100,说明对象确实是DerivedSingleton类型
    
  • 当前实现的隐患:这种单例继承写法有严重问题——如果先调用Singleton::getInstance(),instance会被初始化为基类对象,之后DerivedSingleton::getInstance()会强制转换这个基类指针为派生类指针,此时访问x会触发未定义行为。正确的单例继承应该让派生类拥有自己的静态实例成员,避免共享基类的静态变量。

内容的提问来源于stack exchange,提问作者Gaurav Mehta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 13:13:28