2014-04-26 21 views
5

Tôi đang học lại C++ (có nghĩa là: hãy nhẹ nhàng với tôi! :). Tôi có một siêu lớp (Node) với một phương pháp trừu tượng (step()) phải được thực hiện trong một phân lớp (TestNode). Nó biên dịch mà không có lỗi và không có bất kỳ cảnh báo, nhưng liên kết nó kết quả trong:Tại sao tôi nhận được "Biểu tượng không xác định ... typeinfo ... vtable" với lớp ảo và bê tông?

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) 

Theo như tôi có thể nói, tôi xác định "đầu tiên phi inline hàm thành viên ảo" (ví dụ: TestNode::step()).

Tôi đã đọc các thông báo lỗi một cách cẩn thận, tôi đã đọc bài đăng trên blog here và đã xem xét một số SO bài viết khác (Undefined symbols "vtable for ..." and "typeinfo for..."?, How to find undefined virtual functions of a classes, và c++ a missing vtable error), nhưng tôi cảm thấy không gần gũi hơn với giác ngộ.

Tôi đang thiếu gì?

Đây là toàn bộ chương trình.

#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; 
} 

Trả lời

10

Vấn đề là bạn không cung cấp triển khai cho Node::step(). Nếu bạn thực sự mong muốn Node không thực hiện bước nào, thì bạn nên làm cho nó trở thành một hàm thuần túy ảo Node::step(int count) = 0, do đó làm cho Node trở thành một lớp trừu tượng (bạn không thể trực tiếp khởi tạo nó). Nếu không, hãy xác định một triển khai cho Node :: step.

10

Theo như tôi có thể biết, tôi đã xác định "hàm thành viên ảo không nội dòng đầu tiên" (ví dụ: TestNode :: step()).

Bạn có vẻ khó hiểu với định nghĩa. Những gì bạn có trong lớp cơ sở chỉ là khai báo không có định nghĩa, tức là thực hiện.

Bạn cần phải làm cho nó thuần ảo hoặc triển khai ngay cả khi nó chỉ là một {} trống.

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

Cách giải quyết nhanh chóng có thể là:

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

hay:

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

Tốt (và đầy đủ) câu trả lời - cảm ơn bạn. Để công bằng, @Daniel đã đưa ra một câu trả lời đúng một vài phút trước khi bạn, vì vậy anh ta nhận được một dấu kiểm. –

+0

Với danh tiếng của bạn (15.7k), bạn không cảm thấy bạn có thể hơi hào nhoáng và nhượng bộ này cho Daniel (đại diện 313)? :) Bên cạnh đó, _was_ của anh ta là một câu trả lời hoàn chỉnh cho câu hỏi của tôi: Tôi đã nói trong câu hỏi ban đầu mà tôi muốn làm cho hàm Node :: step() ảo và yêu cầu một lớp con thực hiện nó. Câu trả lời của anh ta đã làm chính xác điều đó. –

+1

@fearless_fool: Tôi không chắc chắn tại sao bạn lại quan tâm đến danh tiếng .. Đó là về Q/A của trang web khi các câu trả lời được chọn bật lên trên cùng. Đó là quyết định của bạn theo một trong hai cách, vì vậy nếu bạn nghĩ rằng đó là một câu trả lời kỹ thuật tốt hơn đi cho nó. – lpapp

Các vấn đề liên quan