有没有办法强制编译器(特别是GCC)使类编译到面向对象的C?具体来说,我想要实现的是写下这个:
class Foo {
public:
float x, y, z;
float bar();
int other();
...etc
};
Foo f;
float result = f.bar()
int obSize = sizeof(Foo);
然后编译完全相同:
Struct Foo { float x, y, z; };
float Foo_bar(Foo *this);
Foo f;
float result = Foo_bar(&f);
int obSize = sizeof(Foo);
我的动机是增加可读性,但不会对Foo的每个对象造成内存损失。我想通常obSize的类实现将是
obSize = sizeof(float)*3 + sizeof(void*)*number_of_class_methods
主要是在内存受限微控制器中使用c ++类。但是,我想如果我让它工作,我也会用它来进行网络序列化(当然在相同的端机上)。
答案 0 :(得分:7)
您的编译器实际上正是为您做的。甚至可以通过将this
指针放在寄存器中而不是将其推入堆栈(这至少是MSVC在Windows上执行的操作)来优化地进行优化,这是标准无法做到的C调用约定。
至于:
obSize = sizeof(float)*3 + sizeof(void*)*number_of_class_methods
void*
表示指向数据的指针,而不是指向代码的指针(它们不需要具有相同的大小)3 * sizeof(float)
。答案 1 :(得分:3)
C ++已经完成了你所讨论的非多态类(没有虚方法的类)。
一般来说,C ++类与C结构具有相同的大小,除非该类包含一个或多个虚方法,在这种情况下,开销将是每个类实例的单个指针(通常称为vptr)。
还有一个'vtbl'实例,每个虚函数都有一组指针 - 但是vtbl将在该类类型的所有对象之间共享(即。每个类类型有一个vtbl,该类对象的各种vptrs将指向同一个vtbl实例。
总之,如果您的类没有虚方法,那么它将不会大于相同的C结构。这符合C ++的理念,即不为你不使用的东西买单。
但是,请注意,C ++类中的非静态成员函数确实采用了参数列表中未明确提及的额外参数(this
指针) - 这基本上就是您在问题中讨论的内容
脚注:在C ++类和结构中,除了默认成员可访问性的细微差别外,它们是相同的。在上面的答案中,当我使用术语“类”时,该行为也适用于C ++中的结构。当我使用术语'struct'时,我在谈论C结构。
另请注意,如果您的类使用继承,则该继承的“开销”取决于继承的确切种类。但是,就多态和非多态类之间的差异而言,无论成本如何,只有在您使用它时才会引入它。
答案 2 :(得分:2)
第一个程序
class X
{
public:
int y;
void method1() {}
};
int main()
{
cout << sizeof(X) << '\n'; // prints 4
}
第二个程序
class X
{
public:
int y;
void method1() {}
void method2() {}
void method3() {}
void method4() {}
void method5() {}
void method6() {}
};
int main()
{
cout << sizeof(X) << '\n'; // also prints 4
}
答案 3 :(得分:1)
实际上,我认为使用类没有特定的内存损失,因为成员函数每个类的实例都存储一次。因此,您的内存占用率更像是1*sizeof(void*)*number_of_class_methods + N*sizeof(float)*3
N
Foo
个实例。
唯一一次额外的惩罚是使用虚函数时,每个对象都带有一个指向vtable的指针。
答案 4 :(得分:0)
你需要测试,但据我所知,如果所述方法是虚拟的,那么只存储指向其方法的指针。否则,结构和类将占用大致相同的内存量(不同的编译器完成不同的对齐等)。