0

I get unresolved external symbol when calling virtual function from virtual destructor.

#include <iostream>

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

  virtual ~Animal() {
    this->Sound();
  }
};

class Dog : public Animal {
public:
  void Sound() override {
    printf("Woof!\n");
  }
};

class Cat : public Animal {
public:
  void Sound() override {
    printf("Meow!\n");
  }
};

int main() {
  Animal* dog = new Dog();
  Animal* cat = new Cat();

  dog->Sound();
  cat->Sound();

  delete dog;
  delete cat;

  system("pause");
  return 0;
}

Why? Also I tried edit destructor to this:

  void Action() {
    this->Sound();
  }

  virtual ~Animal() {
    this->Action();
  }

Now code is compiling, but in destructor I get pure virtual function call. How can I solve it?

cogp
  • 5
  • 1
  • 2
    Does this answer your question? [Calling virtual functions inside constructors](https://stackoverflow.com/questions/962132/calling-virtual-functions-inside-constructors) – Yksisarvinen Apr 03 '20 at 11:41
  • In short: virtual functions mechanism is disabled in both constructors and destructors. Even if it wasn't disabled by standard, by the time `~Animal()` is called all the derived objects are destroyed already, so there's no valid e.g. `Dog` object to call that virtual function on. – Yksisarvinen Apr 03 '20 at 11:43

1 Answers1

2

By the time you call the Animal destructor, the derived class (Dog/Cat) has already had its destructor called, thus it is invalid. Calling Dog::sound() would risk accessing destroyed data.

Thus the destructor call is not allowed to access derived class methods. It tries to access Animal::sound(), but it's pure virtual - hence the error.

Jasper Kent
  • 3,546
  • 15
  • 21
  • So, if I need to call virtual method when object destructs, how can I do it? – cogp Apr 03 '20 at 11:48
  • @cogp You can't. You shouldn't. You need to design your system differently. In the simple case here, you could just call `sound()` directly from the derived class destructors. – Jasper Kent Apr 03 '20 at 12:11