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

时间:2018-01-29 19:21:27

标签: c++ syntax constructor sfml

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,如果我这样做,为什么使用{}作为视频模式参数?在第一种情况下使用()会导致错误。

2 个答案:

答案 0 :(得分:3)

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

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

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

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

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

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

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

在任何C ++版本中,

(1000,800)本身并不是用于构造对象的有效C ++语法。

答案 1 :(得分:2)

  

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

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

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

  

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

因为(1000,800)已经有了不同的旧版本含义:它表示“获取值1000,丢弃该值,然后获取值800”。不可否认,在这种情况下,这一点毫无意义,但是没有办法以(1000,800)在您的情况下工作的方式重写语言,同时合理的先前有效代码也继续有效。