2014-04-26 11 views
5

Aktualizuję C++ (co oznacza: weź mnie delikatnie! :). Mam superklasę (Node) z metodą abstrakcyjną (step()), która musi zostać zaimplementowana w podklasie (TestNode). Kompiluje bez błędów i bez ostrzeżenia, ale łącząc je skutkuje:Dlaczego otrzymuję "Niezdefiniowane symbole ... typeinfo ... vtable" z wirtualną i konkretną klasą?

bash-3.2$ g++ -Wall -o ./bin/t1 src/t1.cpp 
Undefined symbols for architecture x86_64: 
    "typeinfo for test::Node", referenced from: 
     typeinfo for test::TestNode in t1-9f6e93.o 
    "vtable for test::Node", referenced from: 
     test::Node::Node() in t1-9f6e93.o 
    NOTE: a missing vtable usually means the first non-inline virtual member function has no definition. 
ld: symbol(s) not found for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

O ile mogę powiedzieć, mam zdefiniował „pierwszy non-inline funkcji członka wirtualnego” (tj TestNode::step()).

Mam dokładnie przeczytać komunikat o błędzie, czytałem posty na blogach here i spojrzał szereg innych stanowisk (SO Undefined symbols "vtable for ..." and "typeinfo for..."?, How to find undefined virtual functions of a classes i c++ a missing vtable error), ale czuję, że nie bliżej do oświecenia.

Czego mi brakuje?

Oto program w całości.

#include <stdio.h> 

namespace test { 

    class Node { 
    public: 
    virtual Node& step(int count); 
    }; 

    class TestNode : public Node { 
    public: 
    TestNode(); 
    ~TestNode(); 
    TestNode& step(int count); 
    }; 

    TestNode::TestNode() { } 
    TestNode::~TestNode() { } 
    TestNode& TestNode::step(int count) { 
    printf("count = %d\n", count); 
    return *this; 
    } 

} // namespace test  

int main() { 
    return 0; 
} 

Odpowiedz

10

Problemem jest podać żadnego implementację Node::step(). Jeśli naprawdę chcesz, aby Węzeł nie miał implementacji dla kroku, powinieneś uczynić go czysto wirtualną funkcją Node::step(int count) = 0, tym samym czyniąc Node klasą abstrakcyjną (nie możesz jej bezpośrednio utworzyć). W przeciwnym razie zdefiniuj implementację dla węzła :: krok.

10

O ile mogę powiedzieć, zdefiniowałem "pierwszą nieinsertowaną funkcję wirtualnego członka" (tj. TestNode :: step()).

Wydaje się, że definicja jest myląca z deklaracją. To, co masz w klasie bazowej, to tylko deklaracja bez definicji, czyli implementacja.

Musisz albo uczynić go czystym wirtualnym, albo zaimplementować, nawet jeśli jest to pusty {}.

class Node { 
public: 
    virtual Node& step(int count); 
}; 

Szybkie obejście może być:

class Node { 
public: 
    virtual Node& step(int count) = 0; 
           // ^^^ making it pure virtual 
}; 

czyli

class Node { 
public: 
    virtual Node& step(int count) { }; 
           // ^^^ empty implementation for now 
}; 
+0

Dobry (i kompletne) odpowiedź - dziękuję. Aby być uczciwym, @Daniel dał poprawną odpowiedź kilka minut przed twoją, więc dostaje znacznik wyboru. –

+0

Biorąc pod uwagę swoją reputację (15,7 tys.), Czy nie czujesz, że możesz być nieco wspaniałomyślny i oddać go Danielowi (rep. 313)? :) Poza tym jego _ było kompletną odpowiedzią na moje pytanie: w oryginalnym pytaniu powiedziałem, że chcę, aby funkcja Node :: step() była wirtualna i wymagała, aby została ona zaimplementowana przez podklasę. Jego odpowiedź właśnie to zrobiła. –

+1

@fearless_fool: Nie jestem pewien, dlaczego tak bardzo zależy ci na reputacji. Chodzi o Q/A strony, ponieważ wybrane odpowiedzi pojawiają się na górze. To twoja decyzja w obu kierunkach, więc jeśli uważasz, że jest to technicznie lepsza odpowiedź, idź za nią. – lpapp

Powiązane problemy