Home > OS >  So, why do I have to define virtual function in a base class?
So, why do I have to define virtual function in a base class?

Time:11-15

I'm trying to create a simple base abstract class with a virtual function and a child class that defines that virtual function. Running the following produces an error during compilation:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak();

};

class Cat : public Animal{
public:
    void speak() override {
        cout << "Meow!";
    }
};

int main() {
    Cat cat;
    Animal* base = &cat;
    base->speak();
}
// error LNK2001: unresolved external symbol "public: virtual void __thiscall Base::speak(void)" (?speak@Base@@UAEXXZ)

My IDE suggests adding a useless definition for speak() in Animal, and it works:

#include <iostream>
using namespace std;

class Animal {
public:
    virtual void speak();
};

void Animal::speak() {

}

class Cat : public Animal{
public:
    void speak() override {
        cout << "Meow!";
    }
};

int main() {
    Cat cat;
    Animal* base = &cat;
    base->speak();
}

So, why do I have to define virtual function in a base class?

By comparison, in Java there is no such need and even possibility (which makes more sense):

abstract class Animal {
    abstract void speak();
}

class Cat extends Animal {
    void speak() {
        System.out.println("Meow!");
    }
}

public class Main {
    public static void main(String[] args) {
        Animal animal = new Cat();
        animal.speak();
    }
}

CodePudding user response:

Yes, non-pure virtual function should be defined.

[class.virtual]/12:

A virtual function declared in a class shall be defined, or declared pure ([class.abstract]) in that class, or both; no diagnostic is required ([basic.def.odr]).

You might provide a definition, or mark it as pure virtual.

class Animal {
public:
    virtual void speak() = 0;
};

CodePudding user response:

You need to mark it as "abstract" (or "pure virtual" in C lingo) in the base class using = 0.

class Animal {
public:
    virtual void speak() = 0;
};

CodePudding user response:

In C a class is abstract if it has at least one pure virtual function.

This class

class Animal {
public:
    virtual void speak();

};

is not an abstract class because neither pure virtual function is declared in the class.

And a virtual function is specified pure by using a pure-specifier in the function declaration in the class definition.

That is to make the class abstract you should declare its virtual function like

class Animal {
public:
    virtual void speak() = 0;

};

The compiler needs to build a table of pointers to virtual functions where actual addresses of virtual functions will be stored. If the linker is unable to resolve an address of a virtual function then an error will be issued.

Bear in mind that a pure virtual function may be defined. For example you could write

class Animal {
public:
    virtual void speak() = 0;

};

void Animal::speak()
{
    std::cout << "The animal has issued a sound.\n";
}

In the derived class you could define the function for example the following way

class Cat : public Animal{
public:
    void speak() override {
        Animal::speak();
        cout << "Meow!";
    }
};
  • Related