2013-11-22 55 views
2

我使用具有一些虛擬方法的父類。當我在構造函數中調用虛方法時,它會給「error LNK2019: unresolved external symbol "protected: virtual int ... referenced in function "public: __thiscall ...」和「...\Debug\8puzzleProject.exe : fatal error LNK1120: 1 unresolved externals」消息帶來LNK2019LNK1120錯誤。構造函數中的C++調用虛擬方法

有沒有辦法解決這個問題,或者我不應該在構造函數中調用虛方法?

謝謝!

這裏是代碼:

類有錯誤:

#ifndef HEURISTICSEARCH_H 
#define HEURISTICSEARCH_H 

#include "BruteSearch.h" 

class HeuristicSearch: public BruteSearch 
{ 
public: 

    HeuristicSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]); 
    bool search(); 

protected: 

    virtual int calculateUtility() = 0; 
    virtual int calculateUtility(Node*) = 0; 

    bool check4Goal(); 
    void checkNmove(); 
    int findMin(int* values); 

    int utilityCost; 

}; 

#endif 

HeuristicSearch::HeuristicSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]) 
    :BruteSearch(initial) 
{ 
    utilityCost = calculateUtility(); //After deleting this line, the error's gone 
} 

父類的父類的(沒有錯誤)

#ifndef BRUTESEARCH_H 
#define BRUTESEARCH_H 

#include <iostream> 
#include <queue> 

#include "Constants.h" 
#include "Node.h" 

class BruteSearch 
{ 
public: 

    BruteSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]); 
    virtual bool search(){ return false; } 

protected: 

    bool check4Goal(); 
    void printBoard(); 

    int turn; 
    int goalBoard[BOARD_LIMIT][BOARD_LIMIT] ; 

    Node *currentPtr; 

}; 

#endif 
+1

可以請你發佈你的代碼?你單獨使用你的父類嗎?沒有爲虛擬方法提供實現,它將無法正常工作。 – nio

+2

[在構造函數中調用虛函數](http:// stackoverflow。com/questions/962132/calling-virtual-functions-inside-constructors) –

回答

6

我shoudn't打電話在構造函數中的虛擬方法?

這樣做會調用正在構造的類中的重寫,而不一定是最終重寫。這可能不是你想要的,如果函數在當前類中是純虛擬的,那麼這個錯誤通常是不應該的。

在這種情況下,錯誤表明它是純虛擬的,在這個類中沒有實現,所以調用它肯定是一個錯誤。幸運的是,它給了你一個合理友好的鏈接器錯誤,而不是未定義的運行時行爲。 (更新:你發佈的代碼確認猜測 - 你不能從構造函數調用函數)。

有沒有辦法解決這個問題

許多問題可以通過額外的間接水平來解決。我會貫徹啓發式在一個單獨的委託類,而不是一個子類:

struct Heuristic { 
    virtual ~Heuristic() {} // Don't forget this on a polymorphic base class 
    virtual int calculateUtility() = 0; 
    virtual int calculateUtility(Node*) = 0; 
}; 

class HeuristicSearch: public BruteSearch { 
public: 
    HeuristicSearch(Heuristic & h, int initial[BOARD_LIMIT][BOARD_LIMIT]) : 
     BruteSearch(initial), 
     heuristic(h), 
     utilityCost(heuristic.calculateUtility()) // No problem calling this 
    {} 

private: 
    Heuristic & heuristic; 
    int utilityCost; 
    // and so on 
}; 

委託是完全建立之前,我們先來構建搜索類,所以有從構造函數訪問它沒有問題。

或者,爲了避免不必要的運行時多態性,我可能注入委託類型作爲模板參數:

template <class Heuristic> 
class HeuristicSearch: public BruteSearch { 
public: 
    HeuristicSearch(int initial[BOARD_LIMIT][BOARD_LIMIT]) : 
     BruteSearch(initial), 
     utilityCost(heuristic.calculateUtility()) // Doesn't have to be virtual 
    {} 

private: 
    Heuristic heuristic; 
    int utilityCost; 
    // and so on 
}; 
+0

是的,它是一個純虛函數,我在子類中實現它。所以,我想,我得到了答案。 – ciyo

2

當構造一個派生類的對象,基類的一個對象被首先構建。該對象不知道它將成爲派生類的對象。因此,從基類的構造函數調用的任何函數只會針對基類進行解析,而不管該函數是否爲虛擬函數。

在你的情況,HeuristicSearch不提供calculateUtility實現,但HeuristicSearch::calculateUtility()是從HeuristicSearch的constuctor叫,不管HeuristicSearch::calculateUtility()是否是虛擬的或沒有。