在 C++ 中初始化 C 结构
Posted
技术标签:
【中文标题】在 C++ 中初始化 C 结构【英文标题】:Initialise C-structs in C++ 【发布时间】:2012-01-20 14:22:54 【问题描述】:我正在创建一堆 C 结构,因此我可以封装要通过 dll c 接口传递的数据。结构有很多成员,我希望它们有默认值,这样就可以只指定几个成员来创建它们。
据我了解,结构需要保持 c 风格,因此不能包含构造函数。创建它们的最佳方法是什么?我在想工厂?
【问题讨论】:
【参考方案1】:struct Foo
static Foo make_default ();
;
工厂是矫枉过正。当您想要创建给定接口的实例时使用它,但实现的运行时类型在创建站点上不是静态已知的。
【讨论】:
这是工厂吗?尽管是一个函数,而不是一个类型? @dangerousdave:你想要的是一个POD,并且这些都允许有static
成员。
@spraff:那是一个抽象工厂。
拥有一个非抽象的、未封装的“工厂”是没有意义的。它只是添加了毫无意义的行话和OOP-ifying something which is really a function。
@Lightness:我认为“工厂”一词的使用并不一致。它通常像您一样使用,表示任何创建对象的函数或对象。有时它专门用于表示工厂方法模式或抽象工厂模式(我认为两者都有一个带有具体实现的工厂接口,尽管我没有 GoF 书)。将“创造事物的任何事物”定义应用于按值返回的问题在于,它使std::sin
成为工厂——它需要double
并返回一个新创建的double
。所以这有点毫无意义。【参考方案2】:
C-Structs 仍然可以有成员函数。但是,如果您开始使用虚函数,就会出现问题,因为这需要在结构内存的某个位置创建一个虚表。普通成员函数(例如构造函数)实际上不会向结构添加任何大小。然后,您可以毫无问题地将结构传递给 DLL。
【讨论】:
@dangerousdave:如果它不起作用,那么我有很多代码会中断。你能提供更多关于你的“实验”的信息吗?对于没有构造函数的结构和有构造函数的结构,你会得到不同的“sizeof”结果吗? 在 C++11 中,这很好,因为它仍然是一个 standard-layout 类(它可以具有构造函数和其他非虚拟成员函数)。在 C++03 中,这在实践中可能没问题,但不能保证添加构造函数会保持布局。 @Mike Seymour:很公平,以前从未听说过(或者更有经验)。您能告诉我规范中涉及该问题的特定部分吗? C++11, 9/6 定义了 standard-layout 类。我手头没有 C++03 的副本,但从记忆中它的“类”一章,可能是第 9 章,没有定义 standard-layout 的概念,只有 吊舱;并且具有构造函数的类不是 POD。 @Mike Seymour:干杯。我对那个感到震惊,tbh,我不知道。我想我很幸运,我遇到过的任何编译器都不会在这样的事情上变得奇怪:D【参考方案3】:我会使用构造函数类:
struct Foo ... ;
class MakeFoo
Foo x;
public:
MakeFoo(<Required-Members>)
<Initalize Required Members in x>
<Initalize Members with default values in x>
MakeFoo& optionalMember1(T v)
x.optionalMember1 = v;
// .. for the rest option members;
operator Foo() const
return x;
;
这允许在表达式中任意设置结构的成员:
processFoo(MakeFoo(1,2,3).optionalMember3(5));
【讨论】:
一个有效的解决方案,但如果你问我这有点过分。有多个语句来构建一个对象有什么问题?链接并不能在使用时节省工作量,它只是在其他地方添加了冗余代码。 @spraff,没有错,但我个人更喜欢面向表达式的接口,不需要包含中间值的变量。【参考方案4】:我有一个简单的想法,方法如下:
像往常一样制作结构,并创建一个初始化它的简单函数:
struct Foo...;
void Default(Foo &obj)
// ... do the initialization here
如果你有多个结构,你可以在 C++ 中重载函数,所以你可以有很多称为“默认”的函数,每个函数都初始化自己的类型,例如:
struct Foo //... ;
struct Bar //... ;
void Default(Foo &obj) ...
void Default(Bar &obj) ...
C++ 编译器将根据参数知道何时调用第一个或第二个重载。 & 使 obj 成为对您提供的任何参数的引用,因此对 obj 所做的任何更改都将反映到您作为参数放入的变量中。
编辑: 我对如何指定一些参数也有一个想法,你可以使用默认参数来做到这一点。它是这样工作的:
例如你下面的函数;您可以像这样为参数指定默认值:
void Default (Foo &obj, int number_of_something = 0, int some_other_param = 10)
...
【讨论】:
我有时会使用这种方法。您甚至可以添加额外的参数并使用重载来创建各种构造函数。 默认参数“新”究竟如何?它们总是在标准 C++ 中是有效的,而且我认为在此之前已经有相当长的一段时间了。 你说得对,我最近了解到它们,我假设它们是新的。我做了一些研究,现在我知道了:D以上是关于在 C++ 中初始化 C 结构的主要内容,如果未能解决你的问题,请参考以下文章