Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可以在C+中为无行为聚合(bundle-o-data)提供构造函数+;?_C++ - Fatal编程技术网

C++ 可以在C+中为无行为聚合(bundle-o-data)提供构造函数+;?

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

请参考或萨特的第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 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)
};