- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
从下面的代码 sizeof(Base) == 24
和 sizeof(Derived) == 24
。
为什么它们的大小相等?
在 Base
类中我们有 3 个成员,在 Derived
类中我们有另一个成员。
class Base
{
private:
double d;
protected:
long l;
public:
int i;
};
class Derived : public Base
{
private:
float f;
};
最佳答案
碰巧你的类(class)Base
有 8 字节对齐要求,但其最后一个成员的大小为 4。这导致在 Base
末尾添加一个空填充区域的内存布局。当您实例化类 Base
的对象时,额外的填充会发挥作用。本身,即所谓的最衍生对象。
Base b; // <- a most-derived object
Base a[10]; // <- an array of most-derived objects
但是,当您“嵌入”Base
作为类Derived
的基类, 嵌入的 Base
的末尾不需要额外的填充子对象。
Derived d; // <- object `d` contains an embedded sub-object of type `Base`
智能编译器会尝试通过放置类 Derived
的额外字段来重用该区域。进入 Base
中用于填充的布局区域.在您的情况下,额外字段 Derived::f
顺便说一句,它具有相同的 4 个字节大小,即它完全适合那里。最终结果是类的总大小没有增加。
一个非常相似(本质上)的效果就是所谓的“空基优化”。在 C++ 中 sizeof
对于任何类型都保证大于 0,这意味着 sizeof
空类的值总是大于零。但是,当您从空基类派生其他类时,您可能会观察到基类对派生类的大小的贡献正好为 0 字节。例如
struct A {};
struct B {};
struct C {};
struct D {};
struct F : A, B, C, D {
int i;
}
int main() {
std::cout << sizeof(A) << std::endl << sizeof(B) << std::endl <<
sizeof(C) << std::endl << sizeof(D) << std::endl;
std::cout << sizeof(F) << std::endl;
}
即使 sizeof
每个基类的大于零,sizeof(F)
通常仍会评估为 sizeof(int)
,就好像基类子对象根本不存在一样。
换句话说,正如这些示例所示,基类子对象在内存布局方面比大多数派生对象遵循明显更宽松的规则。这些宽松的规则可能很容易导致sizeof
的基类只会部分贡献sizeof
派生类。
关于c++ - 为什么 sizeof(BaseClass) == sizeof(DerivedClass) 虽然我添加了一个成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21220774/
我有很多类都继承自一个基类——实际上它只是一个允许序列化的接口(interface)包装器: public abstract class VoucherRuleBase : IRule{ pu
我是 C# 的新手,我正在开发一个 rpg 游戏引擎。 我有我的基类 Item,它是 Weapon 和 Armour 的父类,武器和盔甲类有额外的变量,用于统计、武器插槽、盔甲类型等。 我的 Play
在使用新语言进行个人项目时,我遇到了一个烦人的编译时错误,我的 constants.h(常量类)的静态成员找不到类名(Quark,它是派生的Particle 类,这两个在同一个文件“Particle.
我无法从 BaseClass 隐式转换到它的DerivedClass .我有以下代码: class BaseClass { } class DerivedClass : BaseClass {
我正在尝试使用工厂方法返回派生类,但返回类型是基类类型。根据我的理解,我认为继承可以让我这样做,显然我错了。 WeightExercise 和 CardioExercise 均派生自 Exercise
我刚刚了解到将泛型参数作为 out 的类型参数强制该泛型类型保持不变。这让我很惊讶。我以为out参数被视为与返回类型相同(即如果泛型参数是协变的,那么它可以用作 out 输出参数),因为它们都是方法的
我遇到段错误但不知道为什么。使用std::unique_ptr(&DerivedClassObj)有问题吗?谢谢。 这是代码 # test.cc #include #include #includ
我尝试了下面的代码,并得到了一个编译错误。 class A {}; class B : public A {}; void f(A*& p) {} int main() { B* pB;
我有这样的基类: public class Scene { public IList Models {get; set;} } public class SceneModel { } 和像这样
我如何传递一个列表,该列表是一个 DerivedObjects 列表,其中方法需要一个 BaseObjects 列表。我正在转换列表 .ToList()并且想知道是否有更好的方法。我的第二个问题是语法
给定以下类定义: public class BaseClass { public string SomeProp1 { get; set; } } public class DerivedCl
我正在尝试传递 DerivedClass 的列表到接受 BaseClass 列表的函数,但我收到错误: cannot convert from 'System.Collections.Generic.
虽然我们可以从基类/接口(interface)继承,为什么我们不能声明一个List<>使用相同的类/接口(interface)? interface A { } class B : A { } cla
从下面的代码 sizeof(Base) == 24 和 sizeof(Derived) == 24。 为什么它们的大小相等? 在 Base 类中我们有 3 个成员,在 Derived 类中我们有另一个
我有一个包含此方法的通用存储库: public void Delete(T item) where T : EntityBase 我正在尝试为某些对象添加软删除行为; IE。删除时,它们不会从数据库中
我需要摆脱这个警告。据我了解,这似乎是因为 DerivedClass 不被视为普通旧数据。我读了关于 POD 的 cppreference和 Standard Layout Type但我仍然不明白为什
我对这个错误有疑问,添加默认构造函数并不能修复它。没有默认构造函数编译会产生错误,使用默认构造函数编译会产生错误。我已经在网上搜索了几个小时,但一无所获。这是我的代码的一个简单示例(实际代码相当长):
我几乎可以肯定我想做的事情有一个合适的术语,但由于我不熟悉它,我将尝试明确地描述整个想法。所以我拥有的是一组类,它们都继承自一个基类。所有类几乎完全由不同的方法组成,这些方法仅在每个类中相关。然而,有
我理解派生类的List<>不能直接赋值给基类的List<>。但是它如何允许将派生类的相同 List<> 分配给 IEnumerable<> 类型的基类参数。 public class Base {}
我有一个构造函数试图初始化基类中的一个字段。编译器提示。该字段 protected ,因此派生类应该具有访问权限。 //The base class: class BaseClass { public
我是一名优秀的程序员,十分优秀!