方便的C ++结构初始化
我试图find一个方便的方式来初始化“pod”C ++结构。 现在,考虑下面的结构:
struct FooBar { int foo; float bar; }; // just to make all examples work in C and C++: typedef struct FooBar FooBar;
如果我想方便地在C(!)中初始化它,我可以简单地写:
/* A */ FooBar fb = { .foo = 12, .bar = 3.4 }; // illegal C++, legal C
请注意,我想明确地避免以下表示法,因为如果我在将来更改结构中的任何内容 ,它会使我打破我的脖子:
/* B */ FooBar fb = { 12, 3.4 }; // legal C++, legal C, bad style?
为了在C ++中实现和/* A */
例子一样的(或者至less类似的),我必须实现一个白痴的构造函数:
FooBar::FooBar(int foo, float bar) : foo(foo), bar(bar) {} // -> /* C */ FooBar fb(12, 3.4);
哪个开水好,但不适合懒惰的人(懒惰是件好事,对吗?)。 而且,它和/* B */
example差不多,因为它没有明确指出哪个值到哪个成员。
所以,我的问题基本上是如何在C ++中实现类似于/* A */
或更好的function? 或者,我可以解释为什么我不应该这样做(即为什么我的心理范式是不好的)。
编辑
方便的话 ,我的意思是可维护和不冗余 。
由于style A
是不允许在C + +,你不想要style B
那么使用style BX
怎么样:
FooBar fb = { /*.foo=*/ 12, /*.bar=*/ 3.4 }; // :)
至less在一定程度上有所帮助。
你的问题有点困难,因为即使是function:
static FooBar MakeFooBar(int foo, float bar);
可能被称为:
FooBar fb = MakeFooBar(3.4, 5);
因为内置数字types的升级和转换规则。 (C从来没有真正强types)
在C ++中,尽pipe在模板和静态断言的帮助下,您可以实现:
template <typename Integer, typename Real> FooBar MakeFooBar(Integer foo, Real bar) { static_assert(std::is_same<Integer, int>::value, "foo should be of type int"); static_assert(std::is_same<Real, float>::value, "bar should be of type float"); return { foo, bar }; }
在C中,你可以命名参数,但你永远不会得到更多。
另一方面,如果你想要的是命名参数,那么你写了很多繁琐的代码:
struct FooBarMaker { FooBarMaker(int f): _f(f) {} FooBar Bar(float b) const { return FooBar(_f, b); } int _f; }; static FooBarMaker Foo(int f) { return FooBarMaker(f); } // Usage FooBar fb = Foo(5).Bar(3.4);
如果你喜欢,你可以胡椒types的促销保护。
如果可以的话,使用GCC。 它的C ++ front.end理解C初始化语法。
在C ++中的另一种方式是
struct Point { private: int x; int y; public: Point& setX(int xIn) { x = Xin; return *this;} Point& setY(int yIn) { y = Yin; return *this;} } Point pt; pt.setX(20).setY(20);
选项D:
FooBar FooBarMake(int foo, float bar)
法律C,法律C ++。 轻松优化POD。 当然,没有命名参数,但是这就像所有的C ++一样。 如果你想命名参数,Objective C应该是更好的select。
选项E:
FooBar fb; memset(&fb, 0, sizeof(FooBar)); fb.foo = 4; fb.bar = 15.5f;
法律C,法律C ++。 命名的参数。
将语句提取到描述它们的函数中(基本重构):
FooBar fb = { foo(), bar() };
我知道风格非常接近你不想使用的风格,但是它可以更容易地replace常量值,并解释它们(因此不需要编辑注释),如果它们改变的话。
你可以做的另一件事(因为你是懒惰的)是使构造函数内联,所以你不必input(除去“Foobar ::”和花费在h和cpp文件之间切换的时间):
struct FooBar { FooBar(int f, float b) : foo(f), bar(b) {} int foo; float bar; };
这个语法怎么样?
typedef struct { int a; short b; } ABCD; ABCD abc = { abc.a = 5, abc.b = 7 };
刚刚在Microsoft Visual C ++ 2015和g ++ 6.0.2上进行了testing。 工作好。
如果你想避免重复variables名称,你也可以制作一个特定的macros。
在C ++中, /* B */
也很好,C ++ 0x也将扩展语法,所以它对于C ++容器也是有用的。 我不明白你为什么称它为坏风格?
如果你想使用名字来表示参数,那么你可以使用boost参数库 ,但是它可能会让不熟悉它的人感到困惑。
重新sortingstruct成员就像重新sorting函数参数一样,如果你不仔细地做这些重构,可能会导致问题。