Why am I getting "Undefined symbols ... typeinfo ... vtable" with a virtual and concrete class?

StackOverflow https://stackoverflow.com/questions/23306790

  •  09-07-2023
  •  | 
  •  

Question

I'm relearning C++ (meaning: go gentle on me! :). I have a superclass (Node) with an abstract method (step()) that must be implemented in a subclass (TestNode). It compiles without error and without any warnings, but linking it results in:

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)

As far as I can tell, I have defined the "first non-inline virtual member function" (i.e. TestNode::step()).

I've read the error message carefully, I've read blog posts here and have looked a number of other SO posts (Undefined symbols "vtable for ..." and "typeinfo for..."?, How to find undefined virtual functions of a classes, and c++ a missing vtable error), but I feel no closer to enlightenment.

What am I missing?

Here's the program in its entirety.

#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;
}
Was it helpful?

Solution

The problem is you provide no implementation for Node::step(). If you truly wish for Node to have no implementation for step, then you should make it a purely virtual function Node::step(int count) = 0, thereby making Node an abstract class (you can not directly instantiate it). Otherwise, define an implementation for Node::step.

OTHER TIPS

As far as I can tell, I have defined the "first non-inline virtual member function" (i.e. TestNode::step()).

You seem to be confusing definition with declaration. What you have in the base class is only declaration without definition, i.e. implementation.

You either need to make it pure virtual or implement it even if it is just an empty {}.

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

The quick workaround could be:

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

or:

class Node {
public:
    virtual Node& step(int count) { };
                               // ^^^ empty implementation for now
 };
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top