C++ 可以在C+中为无行为聚合(bundle-o-data)提供构造函数+;?
请参考或萨特的第41条规则,其中规定: 使数据成员私有,无行为聚合(C样式结构)中除外 为了方便起见,我经常想在这些C风格的结构中添加一个简单的构造函数。例如:C++ 可以在C+中为无行为聚合(bundle-o-data)提供构造函数+;?,c++,C++,请参考或萨特的第41条规则,其中规定: 使数据成员私有,无行为聚合(C样式结构)中除外 为了方便起见,我经常想在这些C风格的结构中添加一个简单的构造函数。例如: struct Position { Position(double lat=0.0, double lon=0.0) : latitude(lat), longitude(lon) {} double latitude; double longitude; }; void travelTo(Position p
struct Position
{
Position(double lat=0.0, double lon=0.0) : latitude(lat), longitude(lon) {}
double latitude;
double longitude;
};
void travelTo(Position pos) {...}
main()
{
travelTo(Position(12.34, 56.78));
}
在使动态构造位置更容易的同时,构造函数还为我初始化默认位置对象
也许我可以按照std::pair的例子提供一个“makePosition”免费函数?NRVO应该和构造器一样快,对吗
Position makePosition(double lat, double lon)
{
Position p;
p.latitude = lat;
p.longitude = lon;
return p;
}
travelTo(makePosition(12.34, 56.78));
我添加了那个微不足道的构造函数,这是否违背了“无行为聚合”概念的精神
编辑:
是的,我知道位置p={12.34,56.78}
。但是我不能用纯C结构做travelTo({12.34,56.78})
编辑2:
对于那些对豆荚类型好奇的人:
跟进:
我问了一个与此问题密切相关的后续问题。我通常为结构提供构造函数,没有任何问题。但是,如果构造函数是“非平凡的”,那么该结构就不再被视为POD类型,并且对如何使用它有限制。如果这对您来说是一个问题(我从来没有遇到过),那么make_XXXX函数显然是一个不错的选择。请注意,如果没有构造函数,以下内容已经满足了您的需要:
int main()
{
Position pos = { 12.34, 56.78 };
travelTo(pos);
Position pos2 = {}; // zero initialises
travelTo(pos2);
}
从概念上讲,这很好——你没有违背“无行为聚合”的精神。问题是结构不再是POD类型,因此标准对其行为的保证更少,并且不能存储在联合中 你考虑过这个吗
Position p = {12.34, 56.78};
我们定期为聚合类型定义构造函数,没有负面影响。事实上,我能想到的唯一不利影响是,在性能关键的情况下,您无法避免默认初始化,并且不能在联合中使用该类型 可供选择的是花括号形式的初始化
Position p = {a,b};
还是一个免费的“制造”功能
前者的问题是,您不能使用它来实例化要传递到函数中的临时对象
void func(Position p)
{
// ...
}
// func({a,b}) is an error
在这种情况下,后者很好,但是对于懒惰的程序员来说,输入的内容稍微多一些。
后一种形式(make函数)的问题在于,它可能会导致您忘记初始化数据结构。因为未初始化的变量让我感觉很不舒服,所以我更喜欢为聚合类型定义构造函数
std::make_pair存在的主要原因实际上并不是因为这个原因(std::pair有构造函数),而是因为要调用模板类型的构造函数,必须传递模板参数,这很不方便:
std::pair<int,int> func()
{
return std::pair<int,int>(1,2);
}
否则,您将允许从双精度转换到某个位置的隐式转换
Position p = 0.0;
这可能会导致意外行为。事实上,我会定义两个构造函数,一个初始化为零,另一个初始化为两个值,因为如果没有纬度和经度,位置构造可能没有多大意义。自从我发布了这个问题以来,我一直在为我的聚合定义构造函数。使用上述我的职位示例,GCC在我这样做时会抱怨:
const Position pos[] =
{
{12.34, 56.78},
{23.45, 67.89},
};
警告:扩展初始值设定项列表仅适用于-std=c++0x或-std=gnu++0x|
相反,我必须这样做:
const Position pos[] =
{
Position(12.34, 56.78),
Position(23.45, 67.89)
};
有了这种解决方法,我担心在嵌入式系统中,我的常量表不会存储在闪存/ROM中
编辑:
我尝试删除Position构造函数,pos数组实际上已经从.bss移到了.rodata段。我不认为遵循
std::pair
和std::make_pair()
所设置的示例与此相关,因为后者是最有益的(在我看来)用于推断std::pair
模板参数的类型。在您的示例中,没有模板,因此,makePosition()
也没有相同的动机。还有另一个动机-创建make函数而不是ctor意味着结构类型仍然是一个POD。您仅限于可以这样使用初始化的地方-例如,你不能用它来为函数调用创建一个无名的临时函数,这是我经常做的事情。我主要想指出的是,聚合语法也提供了零默认值。感谢您将所有这些放在一个答案中。嗯……当我键入所有这些内容时,有很多答案和注释……:)哦,天哪。。。对不起,亚当。我不是在挖苦人,也不是在暗示你在把以前的答案结合起来。:)我很难选择一个答案来接受,直到你发布了一个似乎涵盖了所有角度的答案。嘿,别担心,我不是这么认为的。人们回复stackoverflow的速度之快总是让我感到惊讶,人们不禁要问,人们是如何完成任何工作的!你不是唯一感到惊讶的人!
const Position pos[] =
{
{12.34, 56.78},
{23.45, 67.89},
};
const Position pos[] =
{
Position(12.34, 56.78),
Position(23.45, 67.89)
};