2009-11-13 6 views
0

Je reçois cette erreur de l'éditeur de liens. Je connais un moyen de contourner le problème, mais cela m'embête parce qu'une autre partie du projet est très bien reliée et conçue de façon presque identique.Référence non définie

D'abord, j'ai l'espace de noms LCD. Ensuite, j'ai deux fichiers distincts, LCDText.h et 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 

Et WidgetBignums.h je:

//[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] 

Et je reçois l'erreur de liens suivant:

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

Maintenant, voici une façon de le réparer, mais je ne l'aime pas. Je peux déplacer LCD::TextBignumsDraw en dehors de l'espace de noms LCD et cela fonctionne. Assez étrange, l'éditeur de liens voit LCD::GraphicBignumsDraw. Des indices? Edit: J'utilise gcc 4.4.1-2 sur Fedora 11. Utilisation de SCons pour compiler. Editer: Voici WidgetBignums, montrant 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_; } 
}; 

Édition: Voici la signature de TextBignumsDraw.

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

Edit: Soit dit en passant, je reçois la même erreur pour TextHistogramDraw et TextGifDraw ainsi. TextIconDraw et les autres sont bien.

+0

Comment liez-vous dans la bibliothèque? Quel compilateur/éditeur de liens utilisez-vous? – LeopardSkinPillBoxHat

+0

pouvez-vous poster le fichier de code qui comprend "WidgetBignums.h" .. peut-être WidgetBignums.cpp? –

+0

@Andrew: J'ai inclus la classe elle-même. Dites-moi si vous avez besoin d'autre chose. – Scott

Répondre

3

Où est la définition de LCD::TextBignumsDraw()? C'est ce sur quoi l'éditeur de liens semble se plaindre. Pas la déclaration, mais la définition même de la fonction. Le fait que lorsque vous déplacez la déclaration hors de l'espace de noms LCD les choses commencent à fonctionner indique que la définition de TextBignumsDraw() se trouve dans l'espace de noms global et non dans l'espace de noms LCD.

Ceci (dans certains.fichier cpp):

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

a besoin d'être enveloppé dans un bloc

namespace LCD { 

} 

.

+0

J'ai ajouté l'espace de noms à la signature de la fonction. Étrange que les autres fonctions fonctionnent bien sans elle. Merci pour le coup de pouce. – Scott

1

Essayez laisser tomber le « using namespace LCD », et changer cette ligne 66 à:

Draw = LCD::TextBignumsDraw; 

C'est plus explicite, ce qui peut aider à l'éditeur de liens comprendre ce que vous demandez. En outre, vous ne devez jamais dire "using namespace Anything" dans un fichier d'en-tête. Il hisse tout dans cet espace de noms dans l'espace global pour chaque utilisateur de cet en-tête. Cela détruit presque complètement la valeur d'avoir un espace de noms en premier lieu. Vous devriez sortir les choses comme ça dans le champ le plus étroit possible. Parfois, je mets "using namespace foo" en haut d'une seule fonction, par exemple, si c'est le seul utilisateur des bits dans l'espace de noms dans un fichier .cpp donné.

Questions connexes