错误C2797:列出成员初始化列表中的初始化

时间:2015-01-02 11:34:17

标签: c++ visual-studio inheritance visual-studio-2013

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

  

错误1错误C2797:' NamedRectangle :: _ name':列表初始化   内部成员初始化列表或非静态数据成员初始化程序   没有实现c:\ users \ abhimanyuaryan \ documents \ visual studio   2013 \ projects \ kate demos \ 17   inheritance \ inheritance \ namedrectangle.h 12 1继承

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

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 ++。

3 个答案:

答案 0 :(得分:11)

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

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

  

是的,我们在Update 3中将这些错误插入到编译器中,因为我们对非静态数据成员初始化的实现不完整。

成员初始化列表中的列表/支撑初始化在VS2013中也被破坏。它们的实现问题是illustrated best vector,它有一个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永远不会修复:

  

我们最初计划在Visual Studio 2013的更新中修复此错误,但从工程角度来看,正确的做法是避免另一个问题,并彻底解决初始化的处理问题。但是,由于需要修改的基本代码量,检修编译器架构是一项艰巨的任务。我们无法冒险在更新中创建不兼容性或大错误尾部,因此NSDMI的正确实现只能在主要版本中发布。

显然,修复程序已进入Visual Studio 2015,但永远不会更新到2013年。

答案 1 :(得分:7)

在James和我编写用于MVA日和今天的代码之间有一个编译器更改。发生了什么

 _name{ initial_name }

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

修复方法是切换到圆括号:

 _name(initial_name)

这引起了许多人的混淆,而且我至少有一个客户端为此破坏了工作代码。

答案 2 :(得分:-4)

我解决了。

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;
};

我认为无法初始化因为变量无法找到或加载