2014-04-25 65 views
0

我一直在尋找相當長的一段時間,在我的情況下找不到任何人。對不起,如果這是重複的。錯誤C2512:沒有適當的默認構造函數可用 - 爲什麼如果屬性正在構造函數中初始化?

我有一個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):錯誤C2512:'E ngine':沒有適當的默認構造函數可用

爲什麼如果屬性正在構造函數中初始化? 好的,我理解Chris關於初始化列表的評論。我怎麼能設法評估argc和所有初始化階段?

+3

這些是分配,而不是初始化。使用構造函數初始值設定項列表。 – chris

回答

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創建它們。

+0

感謝您的回答。據我所知,你也沒有選擇在構造函數或其他方法中創建這些字段。你必須在頭文件中聲明它們。所以我在這裏沒有任何選擇,對嗎? – agustinsantiago

+1

是的,我想我應該說得更清楚。每個構造函數都必須爲該類中的每個字段調用構造函數。如果你不指定哪個構造函數,它將成爲默認值。但是,您可以將字段指針指向對象。然後他們可以初始化爲NULL,並且可以在構造函數中用'new'創建它們。 –

+0

謝謝,這就是解決方案。我已經在改變Stage和Engine構造函數,我不喜歡這樣做。非常感謝 – agustinsantiago

1

這裏有一個更好的辦法成員初始化之前做複雜處理,未做對象的生命週期與指針的複雜:

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}); 
相關問題