Pergunta

I have a class declared as follow:

class TestFoo {
public:
    TestFoo();
    virtual void virtualFunction();
    void nonVirtualFunction();
};

that I try to implement this way

TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}

which on compilation returns the error:

undefined reference to vtable for TestFoo

I tried :

TestFoo::TestFoo(){}
void TestFoo::nonVirtualFunction(){}
void TestFoo::virtualFunction(){}

which compiles ok which is consistent to the answers to these posts:

Undefined reference to vtable

undefined reference to vtable

What confuses me is that I thought the whole point of declaring a virtual function is that I would not need to define it. In this example, I am not planning to create any instance of TestFoo, but to create instances of (concrete) classes inheriting from TestFoo. But still, I want to define the function nonVirtualFunction for every subclasses of TestFoo.

Something I did not get right ?

Thanks !

Foi útil?

Solução 3

Your description matches perfectly with the case of an abstract class. Declare your virtual function as:

    virtual void VirtualFunction () = 0;

This means that you are not implementing the function in this class. As a result, the class becomes abstract. That is, no bare objects of this class can be instantiated.

Also, you should provide a virtual destructor.

Update: Some clarifications...

The language allows you to redefine a non-virtual function. Though, the wrong version might be called in some cases:

derived D;    // rB is a reference to base class but it
base & rB=D;  // points to an object of the derived class

rB.NonVirtualFunction ();  // The base-class version is called

For this reason, redefining a non-virtual function is strongly discouraged nowadays. See Scott Meyers' "Effective C++, Third Edition: 55 Specific Ways to Improve Your Programs and Designs", item 36: "Never redefine an inherited non-virtual function."

See also item 7: "Declare destructors virtual in polymorphic base classes". An example:

base * pB = new derived;
delete pB;                // If base's destructor is not virtual,
                          // ~derived() will not be called.

In case you wonder why isn't everything virtual by default, the reason is that calling a virtual function is slightly slower than calling a non-virtual one. Oh, and objects of classes with virtual functions occupy a few more bytes each.

Outras dicas

the whole point of declaring a virtual function is that I would not need to define it

Not quite, it says "I may want to replace the implementation of this function by something else in a derived class."

I may have misunderstood your question, but you seem to imply that you don't think you can define pure virtual member function in C++, which you can. You can declare one as follows.

virtual void virtualFunction() = 0;

Normally, a pure virtual function won't be defined, but of course you can. That says "There is no default implementation of this function because it won't always make sense, but I'll provide you with an implementation that you can opt into."

By the way, if a class has any virtual functions, you should also define a virtual destructor, as it is perfectly legal (and often recommended) to have a base class (smart) pointer to a derived class - without a virtual destructor, the object may not be deleted correctly.

... I thought the whole point of declaring a virtual function is that I would not need to define it ...

For that facility you have a feature called pure virtual methods:

virtual void virtualFunction() = 0;  // no linking error now

Note that, a virtual method cannot remain unimplemented. The reason is that for every virtual method declared inside a class body there has to be a vtable entry. Failing to find its body results in linking error.

Purpose of this restriction:
Unless a class is abstract - that is it has at least one virtual function - there is no way you can guarantee to the compiler that you are not going to declare an object of TestFoo. What happens when you do following:

DerivedOfTestFoo obj1;
TestFoo obj2 = obj1, *p = &obj2; // object slicing
p->virtualFunction(); // where is the body?

Other situation; in constructor there is no virtual mechanism:

TestFoo::TestFoo () {
  this->virtualFunction(); // where is the body?
}

We can conclude that, compilers follow the rule, "Better to be safe than sorry". :)

If you want make this virtual function as pure virtual function,do not want to define it then, virtual void virtualFunction() = 0;

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top