I have the following MWE:
// classes.hpp
#pragma once
struct Base {
virtual ~Base() = default;
virtual void tell() = 0;
};
struct Derived : Base {
Derived() = default;
~Derived() = default;
void tell() override;
};
then,
// classes.cpp
#include <iostream>
#include "classes.hpp"
extern "C" {
Derived* instantiate()
{
return new Derived{};
}
void deinstantiate(Derived* ptr)
{
delete ptr;
}
}
void Derived::tell()
{
std::cout << "Hello!" << std::endl;
}
which I compile on a linux machine as a shared library g++ -fPIC -shared -o classes.so classes.cpp
and the main program:
// main.cpp
#include <iostream>
#include <dlfcn.h>
#include "classes.hpp"
int main()
{
using inst_t = Derived*(*)(void);
using deinst_t = void(*)(Derived*);
void* handle = dlopen("./classes.so", RTLD_NOW);
inst_t inst = reinterpret_cast<inst_t>(dlsym(handle, "instantiate"));
deinst_t deinst = reinterpret_cast<deinst_t>(dlsym(handle, "deinstantiate"));
// some tests here...
Derived* instance = inst();
instance->tell();
deinst(instance);
dlclose(handle);
return EXIT_SUCCESS;
}
which I compile with g++ -ldl -o main main.cpp
It works well. However If I remove the inheritance of Derived
from Base
, i.e. if I substitute above calsses.hpp
file with
// new classes.hpp
#pragma once
struct Derived {
Derived() = default;
~Derived() = default;
void tell();
};
I got a link error
/usr/bin/ld: /tmp/ccLuFAZr.o: in function `main':
main.cpp:(.text+0x66): undefined reference to `Derived::tell()'
collect2: error: ld returned 1 exit status
which I is sensible since it cannot find the symbol from classes.cpp
.
However it is not completely clear to me how subclassing Derived
from Base
can solve this problem since Base
is not used at all. (I think it should be a matter o vtable creation). So
- How is it possible?
- Is there any other way to solve the problem without using (dummy) inheritance?
EDIT
Of course the cause of a linking error can be found in a question whose answers list all the possible cause of linking errors. However, in my opinion this question is by far more generic than mine which deals with a particular situation (the use of dynamic shared library, ecc).
EDIT 2
Non-question: Why, without inheritance, do I get link error? (I know)
Question: Why using inheritance do I not get link error?