错误 C2797:成员初始值设定项列表中的列表初始化

error C2797 : list initialization inside member initializer list

我在看 MVA's tutorial on C++ 我在下面提到的代码是凯特而不是我写的。然而,她似乎在没有编译显示任何错误的情况下解决了它,但在我的情况下,我收到以下错误:

Error 1 error C2797: 'NamedRectangle::_name': list initialization inside member initializer list or non-static data member initializer is not implemented c:\users\abhimanyuaryan\documents\visual studio 2013\projects\kate demos inheritance\inheritance\namedrectangle.h 12 1 Inheritance

代码中的第 12 行来自我的 NameRectangle class,它继承自 Rectangle class:

class NamedRectangle :  public Rectangle
{
public:
    NamedRectangle() { }

    NamedRectangle(std::string initial_name, int initial_width, int initial_height)
        : Rectangle{ initial_width, initial_height }, _name{ initial_name } //--> This line
    {}  

std::string get_name() const { return _name; }

private:
    std::string _name;

};

当我从构造函数中删除 std::string initial_name 以及 _name{initial_name} 时,代码编译。请解释我,不要把我当作一个更高标准的有经验的程序员。我昨天才开始学 C++。

我解决了

class Namedrectangle : public Rectan
{
    public:
    Namedrectangle(){}

    Namedrectangle(string intname, int init_width, int init_height) 
         : Rectan{ init_width, init_height }
    {
        this->_name=intname;************
    }

    string get_name() const
    {
        return _name;
    }

    private:
    string _name;
};

我认为由于找不到或加载变量而无法初始化

从 James 和我编写用于 MVA 日的代码到今天,编译器发生了变化。发生的事情是

 _name{ initial_name }

被解释为创建一个包含其中一项的初始化列表,并使用它来初始化成员变量。这是你做不到的。

解决方法是切换到圆括号:

 _name(initial_name)

这让很多人感到困惑,我至少有一个客户因为这破坏了工作代码。

tl;dr:Kate 的回答中的解决方案适用于 OP;解释不正确。有问题的代码实际上是正确的,并且可以在 VS2015 中编译。该错误(在 VS2013 更新 3 中)是 MS 如何处理在 VS2013 RTM 中发现的错误的结果(他们实际上并没有通过更新修复它,但他们确实破坏了一些工作代码)。它已在 VS2015 中正确修复。


您的代码在 VS2015 中运行良好。 According to Microsoft,在 VS2013 中,

Yes, we inserted these errors into the compiler in Update 3 because our implementation of non-static data member initialization was incomplete.

List/braced 成员初始化列表中的初始化在 VS2013 中也被破坏。他们实现的问题是 illustrated bestvector,它有一个 initializer_list 构造函数, 应该 贪婪地匹配任何使用带有可转换参数的大括号的初始化, 但它没有这样做:

struct S {
    S() : v1{1} {} // C2797, VS2013 RTM incorrectly calls 'vector(size_type)'

    std::vector<int> v1;
    std::vector<int> v2{1, 2}; // C2797, VS2013 RTM incorrectly calls 
                               // 'vector(size_type, const int &)'
};

编译器太容易退回到正常的重载解析。它不使用 std::initializer_list 构造函数,而是调用 size_t 构造函数。正如他们的评论所表明的那样,这是错误的!因此,由于其实施存在缺陷,Microsoft 决定禁用在此上下文中使用支撑初始化的能力。

对于 std::string s,应该没有问题,因为 s{"duh"} 的正确做法是 调用 std::string(const char*),但是由于这个缺陷,MS 无论如何都会给出一个错误。解决方法是明确使用括号代替大括号(或升级到 VS2015),如 Kate 的回答中所述。但错误的正确原因如上所述。

这适用于非静态数据成员初始化 (NSDMI) 以及初始化列表。这在 Visual C++ Team Blog 中有更多解释。至于为什么 VS2013 一直没有修复:

We originally planned to fix this bug in an update to Visual Studio 2013, but from an engineering perspective, the right thing to do is to avoid another kludge and thoroughly address the handling of initialization. But overhauling compiler architecture is a massive task due to the amount of fundamental code that needs to be modified. We could not risk creating incompatibilities or large bug tails in an update, so a correct implementation of NSDMI could only be shipped in a major release.

显然,该修复已在 Visual Studio 2015 年发布,但永远不会出现在 2013 年的更新中。