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.
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!";
}
};