Empty Class(空类)的作用

本文探讨了C++中空类的应用及其如何通过私有继承禁止复制构造和赋值操作。介绍了如何利用空基类优化(EBO)减少派生类的内存占用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假如有一个这样的类,没有数据成员和操作(除了本身默认存在的构造函数、复制构造函数、析构函数、copy assignment函数),那么,它能做什么?

class Empty
{
};

一开始我也是以为这样的空类能够有什么作用呢,直到我看了[1],才感叹自己如此肤浅(所以也建议你去看:)

先假设我们有个很傲娇的类,它不希望通过构造函数生成,也不希望别的对象对它赋值。很不巧,如果我们没有在类中声明复制构造函数或者赋值操作符,那么编译器会为我们默认生成。

那么如何防止这样的事情发生呢?
将复制构造函数和赋值操作符声明为私有

像这样:

class SomeClass
{
    private:
    SomeClass(const SomeClass&);
    SomeClass& operator=(const SomeClass&);
    ...
};

那么当有以下操作都是非法的:

//假如有SomeClass s;
SomeClass scopy(s);//error
s = scopy;//error

然而更加高级的做法是定义一个空类,将空类的复制构造函数和赋值操作符声明为私有,然后让SomeClass继承它。像这样:

class Empty
{
protected:
    Empty(){}                    //允许derived class调用
    ~Empty(){}
private:
    Empty(const Empty&);            //阻止了copying
    Empty& operator = (const Empty&);
};

class SomeClass: private Empty
{
    ...
};

当有人尝试拷贝SomeClass 对象时,编译器会试着去调用base class,也就是Empty 的 copy 构造函数,然后因为private 而告终。

另一个方面,一个空类没有数据成员,理应是不占内存的。
但是sizeof运用于空类的话,会发现空类大小为1。
引用[1]中的原话:

然而,由于技术上的理由,C++裁定凡是独立(非附属)对象都必须有非零大小
通常C++ 官方勒令默默安插一个char 到空对象内。

但,这个约束并不适用于derived class对象内的base class成分,因为它们并非独立。

也就是说,如下:

class SomeClass1
{
private:
    int x;
    Empty e;
};

class SomeClass2: public Empty
{
private:
    int x;
}:

sizeof(SomeClass1) == 8;
sizeof(SomeClass2) == 4;

Someclass1 占用内存肯定不等于一个int,而且因为内存对齐的原因,结果占用内存达到了8;

这是所谓的EBO(empty base optimization:空白基类最优化)

[参考资料]
[1] [1] Scott Meyers 著, 侯捷译. Effective C++ 中文版: 改善程序技术与设计思维的 55 个有效做法[M]. 电子工业出版社, 2011.(条款06:若不想使用编译器自动生成的函数,就该明确拒绝、条款39:明确而审慎地使用private 继承)

<think>嗯,用户让我解释这段Python代码: class EmptyClass: pass empty = EmptyClass() print(type(empty)) 首先,我需要确认用户对Python的基础知识了解多少。可能他们刚开始学习面向对象编程,或者对类和实例的概念不太清楚。让我一步步拆解代码。 首先,定义了一个名为EmptyClass的类,里面只有一个pass语句。pass在Python中通常用作占位符,表示这个类没有属性和方法。所以EmptyClass是一个空类。 接下来,创建了一个EmptyClass的实例empty。这里可能需要解释什么是实例化,即根据类创建对象的过程。用户可能对类和实例的关系不太清楚,需要简单说明类就像蓝图,实例是根据蓝图创建的具体对象。 然后,打印type(empty)的结果。type()函数返回对象的类型。这里emptyEmptyClass的实例,所以输出应该是<class '__main__.EmptyClass'>。需要解释这个输出的含义,说明实例属于哪个类,以及__main__的含义,可能涉及模块的概念。 用户可能想知道为什么即使类里什么都没有,实例还是能被创建。这时候需要强调类默认继承自object,pass只是表示实现,但类的基本结构已经存在,所以可以实例化。 还可能存在的疑问是,这样的空类有什么用?可以提到有时作为占位符,或者动态添加属性和方法的情况,比如在测试或某些设计模式中。 另外,检查是否有语法错误,比如类的定义是否正确,实例化的写法是否正确。确认代码没有问题,运行结果符合预期。 总结用户的疑问点:理解类定义、实例化过程、空类的用途以及type()函数的作用。需要逐一解答这些点,用简单易懂的中文,避免技术术语过多,必要时举例说明。</think>这个Python代码演示了如何创建空类及其对象类型判断,以下是逐行解释: 1. `class EmptyClass:` - 定义了一个名为EmptyClass空类 - 使用`pass`表示这个类不包含任何属性和方法 - 等价于: ```python class EmptyClass(object): # 默认继承object基类 pass ``` 2. `empty = EmptyClass()` - 创建EmptyClass类的一个实例(对象) - 即使类中没有定义内容,仍然可以创建实例对象 - 内存中会为这个对象分配存储间 3. `print(type(empty))` - 输出:`<class '__main__.EmptyClass'>` - `type()`函数返回对象的类型 - `__main__`表示这个类定义在当前执行的主模块中 应用场景示例: ```python # 可以动态添加属性 empty.name = "临时对象" empty.value = 42 # 也可以添加方法 def show_info(self): print(f"Name: {self.name}, Value: {self.value}") empty.show = show_info empty.show() # 输出:Name: 临时对象, Value: 42 ``` 空类的常见用途: - 作为占位符类(后期补充内容) - 创建简单的数据结构(通过动态添加属性) - 实现原型模式或鸭子类型 - 作为测试用的模拟对象(Mock)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值