C / C++,  Programming

[C/C++] undefined reference to ‘vtable for X’

C++ code를 build하다보면 virtual keyword를 종종 사용하게 되는데, 간혹 다음과 같은 error를 볼 수 있다.

/tmp/ccBNrCln.o: In function `my_ns::Animal::Animal()':
main.cpp:(.text._ZN5my_ns6AnimalC2Ev[_ZN5my_ns6AnimalC5Ev]+0x13): undefined reference to `vtable for my_ns::Animal'
/tmp/ccBNrCln.o: In function `my_ns::Animal::~Animal()':
main.cpp:(.text._ZN5my_ns6AnimalD2Ev[_ZN5my_ns6AnimalD5Ev]+0x13): undefined reference to `vtable for my_ns::Animal'
/tmp/ccBNrCln.o: In function `my_ns::Cat::Cat()':
main.cpp:(.text._ZN5my_ns3CatC2Ev[_ZN5my_ns3CatC5Ev]+0x20): undefined reference to `vtable for my_ns::Cat'
/tmp/ccBNrCln.o: In function `my_ns::Cat::~Cat()':
main.cpp:(.text._ZN5my_ns3CatD2Ev[_ZN5my_ns3CatD5Ev]+0x13): undefined reference to `vtable for my_ns::Cat'
/tmp/ccBNrCln.o:(.rodata._ZTIN5my_ns3DogE[_ZTIN5my_ns3DogE]+0x10): undefined reference to `typeinfo for my_ns::Animal'
collect2: error: ld returned 1 exit status

이는 virtual keyword를 사용하고 난 뒤에 상속받은 class에서 해당 function을 구현해주지 않아 발생한 문제다. 아래 예시 코드를 보자.

#include <iostream>        
    
namespace my_ns    
{    
    
class Animal    
{    
public:    
    explicit Animal() {    
        std::cout << "Call Animal" << std::endl;
    }    
    virtual ~Animal() {}   
    virtual void bark (void) = 0;
};    
    
class Dog : public Animal  
{    
public:    
    explicit Dog() {       
        std::cout << "Call Dog" << std::endl;
    }    
    virtual ~Dog() {}      
    virtual void bark (void) {
        std::cout << "Wall Wall" << std::endl;
    }    
};    
    
class Cat : public Animal  
{    
public:    
    explicit Cat() {       
        std::cout << "Call Cat" << std::endl;
    }    
    virtual ~Cat() {}      
    virtual void bark (void);
};    
};    
    
int main()    
{    
    my_ns::Dog dog;        
    my_ns::Cat cat;        
    return 0;    
}

위 코드를 보면 destructor와 bark 함수가 virtual로 선언되어 있는데, Cat class에선 bark을 description 해주지 않았다. 그러나 log에선 bark에 대한 정보는 따로 나와있지 않아서 debugging을 하는데 어려움이 있을 수 있다.

결론은 모든 virtual function을 구현해줘야 해당 문제가 해결된다. 아래와 같이 코드를 수정하면 build가 정상적으로 된다.

#include <iostream>        
    
namespace my_ns    
{    
    
class Animal    
{    
public:    
    explicit Animal() {    
        std::cout << "Call Animal" << std::endl;
    }    
    virtual ~Animal() {}   
    virtual void bark (void) = 0;
};    
    
class Dog : public Animal  
{    
public:    
    explicit Dog() {       
        std::cout << "Call Dog" << std::endl;
    }    
    virtual ~Dog() {}      
    virtual void bark (void) {
        std::cout << "Wall Wall" << std::endl;
    }    
};    
    
class Cat : public Animal  
{    
public:    
    explicit Cat() {       
        std::cout << "Call Cat" << std::endl;
    }    
    virtual ~Cat() {}      
    virtual void bark (void) {
        std::cout << "Nyaong Nyaong" << std::endl;
    }    
};    
};    
    
int main()    
{    
    my_ns::Dog dog;        
    my_ns::Cat cat;        
    return 0;    
}

Leave a Reply

Your email address will not be published. Required fields are marked *