2009-11-13 136 views
0

我收到此鏈接器錯誤。我知道一個解決方法,但它是在竊聽我,因爲項目的另一部分鏈接很好,它的設計幾乎完全相同。未定義的參考

首先,我有命名空間LCD。然後我有兩個單獨的文件,LCDText.h和LCDGraphic.h。

LCDText.h:

//[snip] 
void TextDraw(Widget *w); 

void TextBarDraw(Widget *w); 

void TextHistogramDraw(Widget *w); 

void TextIconDraw(Widget *w); 

void TextBignumsDraw(Widget *w); 

void TextGifDraw(Widget *w); 

}; // End namespace 

LCDGraphic.h:

//[snip] 
void GraphicDraw(Widget *w); 

void GraphicIconDraw(Widget *w); 

void GraphicBarDraw(Widget *w); 

void GraphicHistogramDraw(Widget *w); 

void GraphicBignumsDraw(Widget *w); 

void GraphicGifDraw(Widget *w); 

}; // End namespace 

而在WidgetBignums.h我:

//[snip] 
using namespace LCD; 

extern void TextBignumsDraw(Widget *w); 
extern void GraphicBignumsDraw(Widget *w); 

template <class T> 
WidgetBignums<T>::WidgetBignums(Generic<T> *v, std::string n, Json::Value *section, 
    int row, int col) : Widget(n, section, row, col, 
    WIDGET_TYPE_BIGNUMS | WIDGET_TYPE_RC | WIDGET_TYPE_SPECIAL) { 

    if(v->GetType() == LCD_TEXT) 
     Draw = TextBignumsDraw; // Line 66 
    else if(v->GetType() == LCD_GRAPHIC) 
     Draw = GraphicBignumsDraw; 
    else 
     Draw = NULL; 
//[snip] 

我得到下面的連接錯誤:

LCDControl.o: In function `WidgetBignums': 
/home/starlon/Projects/LCDControl/WidgetBignums.h:66: undefined reference to `LCD::TextBignumsDraw(LCD::Widget*)' 

現在有一種方法來解決它,但我不喜歡它。我可以在LCD命名空間之外移動LCD::TextBignumsDraw,它可以工作。奇怪的是,鏈接器看到LCD::GraphicBignumsDraw。任何線索?

編輯:我在Fedora 11上使用gcc 4.4.1-2。使用SCons進行編譯。

編輯:這裏是WidgetBignums,顯示Draw

template <class T> 
class WidgetBignums : public Widget { 
    Generic<T> *visitor_; 
    std::vector<char> FB_; 
    std::vector<char> ch_; 
    int min_; 
    int max_; 
    int update_; 
    int layer_; 
    Property *expression_; 
    Property *expr_min_; 
    Property *expr_max_; 

    QTimer *timer_; 

    void (*Draw)(Widget *); 

    public: 
    WidgetBignums(Generic<T> *visitor, std::string name, Json::Value *section, int row, int col); 
    ~WidgetBignums(); 
    void TextScroll() {}; 
    void SetupChars(); 
    void Update(); 
    void Start(); 
    void Stop(); 
    std::vector<char> GetFB() { return FB_; } 
    std::vector<char> GetCh() { return ch_; } 
    Generic<T> *GetVisitor() { return visitor_; } 
}; 

編輯:這是TextBignumsDraw的簽名。

//[snip] 
void TextBignumsDraw(Widget *w) { 
//[snip] 

編輯:順便說一句,我得到了同樣的錯誤了TextHistogramDrawTextGifDraw爲好。 TextIconDraw和其他人都很好。

+0

你是如何鏈接圖書館?你正在使用哪個編譯器/鏈接器? – LeopardSkinPillBoxHat 2009-11-13 05:51:08

+0

你可以發佈包含「WidgetBignums.h」的代碼文件..也許WidgetBignums.cpp? – 2009-11-13 05:53:15

+0

@Andrew:我包括這個類。告訴我你是否需要別的東西。 – Scott 2009-11-13 05:58:40

回答

3

LCD::TextBignumsDraw()的定義是什麼?這是鏈接器似乎在抱怨的內容。不是聲明,而是函數的實際定義。

事實上,當您將聲明從命名空間LCD移出時,表示TextBignumsDraw()的定義位於全局名稱空間中,而不是LCD名稱空間中。

這(在一些情況下。CPP文件):

void TextBignumsDraw(Widget *w) { 
    // ... 
} 

需要被包裹在一個

namespace LCD { 

} 

塊。

+0

我將該命名空間添加到該函數的簽名中。奇怪的是,沒有它的其他功能正常工作。感謝您的推動。 – Scott 2009-11-13 06:19:37

1

嘗試去掉了「使用命名空間LCD」,並更改了該行66:

Draw = LCD::TextBignumsDraw; 

這更加明確,這可以幫助瞭解連接你問什麼。

另外,你不應該在頭文件中說「using namespace Anything」。它將該名稱空間中的所有內容都提升到全局空間中,以便每個用戶使用該頭文件。這幾乎完全破壞了首先擁有名稱空間的價值。你應該在最實際的範圍內把這樣的事情提出來。有時候我會在單個函數的頂部放置「using namespace foo」,例如,如果這是給定.cpp文件中命名空間中唯一位的用戶。