错误 C2512:没有适当的默认构造函数可用 - 为啥在构造函数中初始化属性?

Posted

技术标签:

【中文标题】错误 C2512:没有适当的默认构造函数可用 - 为啥在构造函数中初始化属性?【英文标题】:Error C2512: no appropriate default constructor available - Why if properties are being initialized in constructor?错误 C2512:没有适当的默认构造函数可用 - 为什么在构造函数中初始化属性? 【发布时间】:2014-04-25 03:01:01 【问题描述】:

我已经搜索了很长一段时间,但找不到像我这样的人。抱歉,如果这是重复的。

我有一个 Game 类,在 Game.h 中定义:

class Game

    public:
        Game(int argc, char **argv);
        ~Game();

    private:
        Logger logger;
        Stage stage;
        Engine engine;
;

然后在 Game.cpp 中:

Game::Game(int argc, char **argv)

        // Some code removed for clarity. Consider filename and bitsPerPixel 
        // already defined.

        string fileName;
        if (argc != 2)
            fileName = defaultYAMLFilename;
            logger.logBadParam(argc, fileName);
         else 
            fileName = argv[1];
        

        logger = Logger();

        stage = Stage(fileName);

        engine = Engine(stage.getWidthPx(), stage.getHeightPx(), bitsPerPixel, stage.getTimeStep());

然后我得到这个错误:

game.cpp(7): 错误 C2512: 'WormsModel::Stage' : 没有合适的默认构造函数可用

game.cpp(7): error C2512: 'Engine' : 没有合适的默认构造函数可用

为什么要在构造函数中初始化属性? 好的,我了解 Chris 关于初始化列表的评论。我怎样才能设法评估 argc 以及初始化 Stage 的所有内容?

【问题讨论】:

这些是赋值,而不是初始化。使用构造函数初始化列表。 【参考方案1】:

只要类中有字段,就会有一个没有参数的隐式构造。如果要使用非默认构造函数初始化字段,则必须使用初始化器,如下所示:

Game::Game(int argc, char **argv) : logger(), 
                                    stage(fileName), 
                                    engine(stage.getWidthPx(), 
                                           stage.getHeightPx(), 
                                           bitsPerPixel, 
                                           stage.getTimeStep())

     /* remainder of constructor here */

除非这可能行不通,因为您可能在构造函数中做了一些工作来初始化fileNamebitsPerPixel。但这是您遇到的问题。如何解决它取决于您。

每个构造函数都必须为类中的每个字段调用一个构造函数。如果您不指定哪个构造函数,它将是默认值。但是,您可以使字段指针指向对象。然后它们可以初始化为 NULL,您可以在构造函数中使用 new 创建它们。

【讨论】:

感谢您的回答。据我所知,您也没有在构造函数或其他方法中创建这些字段的选项。您必须在标题中声明它们。所以我在这里别无选择,对吗? 是的,我想我应该更清楚地说明这一点。每个构造函数都必须为类中的每个字段调用一个构造函数。如果您不指定哪个构造函数,它将是默认值。但是,您可以使字段指针指向对象。然后它们可以初始化为 NULL,您可以在构造函数中使用 new 创建它们。 谢谢,这就是解决方案。我已经在更改 Stage 和 Engine 构造函数,我不喜欢这样做。非常感谢 @BenVoigt 指针可能不是解决此问题的最佳方法。但有时指针是一个很好的答案。【参考方案2】:

这是在成员初始化之前进行复杂处理的更好方法,而不会使指针的对象生命周期变得复杂:

struct GameOptions

    std::string YAMLFilename;

    GameOptions(int argc, char** argv);
;

GameOptions::GameOptions(int argc, char** argv)

    if (argc != 2)
        YAMLFilename = defaultYAMLFilename;
        logger.logBadParam(argc, fileName);
     else 
        YAMLFilename = argv[1];
    


Game::Game(GameOptions&& opts) : logger()
                               , stage(opts.YAMLFilename )
                               , engine(stage.getWidthPx(), 
                                        stage.getHeightPx(), 
                                        bitsPerPixel, 
                                        stage.getTimeStep())

     /* remainder of constructor here */

并将其称为

Game theGame(GameOptions(argc, argv));

甚至

Game theGame(argc, argv);

【讨论】:

以上是关于错误 C2512:没有适当的默认构造函数可用 - 为啥在构造函数中初始化属性?的主要内容,如果未能解决你的问题,请参考以下文章

错误 C2512:'Building':没有合适的默认构造函数可用

错误 C2512:没有合适的默认构造函数可用(不是类)

错误 C2512 但我有可用的默认构造函数

错误 C2512 没有合适的默认构造函数,即使我有一个?

没有适当的默认构造函数可用错误

使用模板类数据成员的c ++“没有适当的默认构造函数可用”错误