【问题标题】:C++ Pure Virtual Functions Make Class Size LargerC++ 纯虚函数使类规模更大
【发布时间】:2017-09-27 14:19:31
【问题描述】:

我的数学库大量使用接口。它的工作方式是我有一个接口,例如 IVector,然后子类可以派生/实现它。这样做的原因是所有向量都需要能够与另一个向量进行点积,并且我不想出于某种原因忘记它,所以最好有它。 但是,这些并不完全是接口。例如,获取向量大小的实现并不特定于每个向量结构,所以我只是将它放在 IVector 中。我还有一个 Vector 命名空间,它从 IVector 接口调用函数,所以我也可以使用 Vector::Dot(a, b),而不是 a.Dot(b)。

这种设置工作得很好,但有一个大问题:实现接口的结构体的大小更大。经过一番测试,我发现这是纯虚函数的原因:

#include <iostream>
using namespace std;

#define PRINT(thing) cout << thing << endl

struct A
{
    virtual void F() = 0;
};

class B final : public A
{

};

class C
{
    void F()
    {

    }
};

class D : public C
{

};


void main()
{
    PRINT(sizeof(A)); // 4
    PRINT(sizeof(B)); // 4
    PRINT(sizeof(C)); // 1
    PRINT(sizeof(D)); // 1
    cin.get();
}

我认为原因是 vpointer,但我不确定。

但即使发生这种情况是有道理的,为什么在 C# 中实现接口时结构的大小没有变得更大?这是我运行的测试(并不是说我使用 Marshal.SizeOf 获得相同的结果,但它不适用于接口):

using System;
using DotNetCross.Memory;

interface IStuff
{
    void DoStuff();
}

interface IPlsStop : IStuff
{
    void Whatevah();
}

struct Stuff : IPlsStop
{
    public void DoStuff()
    {

    }

    public void Whatevah()
    {

    }
}

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(Unsafe.SizeOf<Stuff>());    // 1
        Console.WriteLine(Unsafe.SizeOf<IStuff>());   // 8
        Console.WriteLine(Unsafe.SizeOf<IPlsStop>()); // 8

        Console.ReadKey();
    }
}

我认为接口只是纯抽象类的糖,但显然它们不是。我假设接口本身的大小更大,因为它们是引用类型。

那么为什么 C# 接口不占用更多内存,而 C++ 纯虚函数却占用更多内存?

这个问题给我带来了太多问题,我必须解决它。我最想知道的是,我可以做些什么来使 C# 类似于 C++ 中的接口(这样我就可以在类不变得更大的情况下实现它们)。

【问题讨论】:

  • 为什么您会对 C++ 和 C# 中对象的行为不同感到惊讶?它们是完全不同的语言,具有不同的规范和实现。无论如何yes the change in sizeof is because of the virtual function(s)
  • 在 C++ 中,结构的大小 - 一般而言 - 取决于编译器如何实现的细节。根据 C++ 标准,它是实现定义的,因此不同的编译器可以 - 实际上会 - 给出不同的结果。您声称不同的大小会导致“太多问题” - 唯一可能发生的方法是您编写的代码依赖于(或假设)具有特定大小的对象。而且,除了一些非常特殊的情况,这是程序设计不佳的标志。
  • “我的数学库大量使用接口。”也许这就是你必须解决的问题。 Virtuals 占据空间不是一个“问题”,而只是一个事实。编写 C++ 时不要受到 C#(或 java?)的启发
  • #define PRINT(thing) cout &lt;&lt; thing &lt;&lt; endl,你应该使用(内联)函数而不是 MACRO。
  • 尝试采用 C# 接口的大小是否有意义 - 它是实现它的类或结构必须具有的方法/属性/等的定义。你不能创建一个接口的实例——所以它的大小是没有意义的。你说尺寸问题会给你带来问题——究竟是什么问题。

标签: c# c++ sizeof pure-virtual


【解决方案1】:

C# 类的编组大小描述了存储它所需的字节数。这与接口无关。

C++ 类的大小描述了实现它所需的内存量。

这是 2 个不同的概念,并解释您观察到的差异

【讨论】:

    猜你喜欢
    • 2013-06-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-04
    • 1970-01-01
    • 2014-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多