何时在构造函数中使用 {} ()

When to use {} () in constructors

本文关键字:构造函数 何时      更新时间:2023-10-16

Game.h中,我有一个名为Game的类:

class Game
{
public:
Game();
void run();
private:
sf::Event e;
sf::RenderWindow app;
sf::Clock delay;
unsigned counter = 0;
Ice *ball = new Ice(app);
Players *players = new Players(app);
Collision collision;
void handleEvent();
};

然后,在Game.cpp中,我使用:

Game::Game() : app({1000,800},"NAME")
{
}

语法

Game::Game() : app(sf::VideoMode(1000,800),"NAME")
{
}

也有效。

我的问题是:为什么在第一种情况下我可以省略sf::VideoMode,如果我这样做,为什么我必须对视频模式参数使用{}?在第一种情况下使用()会导致错误。

您的Game构造函数正在调用以下sf::RenderWindow构造函数:

RenderWindow (VideoMode mode, const String &title, Uint32 style=Style::Default, const ContextSettings &settings=ContextSettings())

您必须向它传递一个完全构造的sf::VideoMode对象。

您的两个示例都在sf::RenderWindow构造函数调用中内联构造一个临时VideoMode对象。 它们都调用以下sf::VideoMode构造函数,只是使用不同的语法:

VideoMode (unsigned int modeWidth, unsigned int modeHeight, unsigned int modeBitsPerPixel=32)

C++11引入了一个名为"统一初始化"的新功能,它将不同上下文中使用的各种不同类型的初始化语法统一到使用大括号的单个语法中,从而大大简化了编码。 在这种情况下,列表初始化用于使用braced-init-list初始化临时对象。正是此功能允许您{1000,800}示例直接在函数参数中构造临时sf::VideoMode对象,而无需显式声明其类名。

早期C++版本没有"统一初始化"。 在这些版本中,构造函数只能按名称显式调用。 这就是允许您sf::VideoMode(1000,800)示例构造临时sf::VideoMode对象的原因(它在 C++11 及更高版本中仍然是有效的语法)。

(1000,800)本身C++用于构造对象的语法都无效,在任何C++版本中。

为什么在第一种情况下我可以省略sf::VideoMode

因为app构造函数的第一个参数被声明为已经具有类型sf::VideoMode

这与你可以编写long v = 1;而不必编写long v = long{1};或类似的东西的原因相同:编译器知道正在初始化的变量或参数的类型,并且可以检查该类型是否支持使用您指定的初始化器进行构造,即使初始化器没有相同的类型。

如果我这样做,为什么我必须使用{}作为视频模式参数?

因为(1000,800)已经有了不同的更古老的含义:它的意思是"获取值1000,丢弃它,然后800获取值"。诚然,在这种情况下,这是没有意义的,但是没有办法重写语言,使(1000,800)在您的情况下工作,同时合理的先前有效的代码也继续工作。