What are undefined reference/unresolved external symbol errors? What are common causes, and how do I fix and prevent these errors?
Class members:
A pure virtual
destructor needs an implementation.
Declaring a destructor pure still requires you to define it (unlike a regular function):
struct X
{
virtual ~X() = 0;
};
struct Y : X
{
~Y() {}
};
int main()
{
Y y;
}
//X::~X(){} //uncomment this line for successful definition
This happens because base class destructors are called when the object is destroyed implicitly, so a definition is required.
virtual
methods must either be implemented or defined as pure.
This is similar to non-virtual
methods with no definition, with the added reasoning that
the pure declaration generates a dummy vtable and you might get the linker error without using the function:
struct X
{
virtual void foo();
};
struct Y : X
{
void foo() {}
};
int main()
{
Y y; //linker error although there was no call to X::foo
}
For this to work, declare X::foo()
as pure:
struct X
{
virtual void foo() = 0;
};
Non-virtual
class members
Some members need to be defined even if not used explicitly:
struct A
{
~A();
};
The following would yield the error:
A a; //destructor undefined
The implementation can be inline, in the class definition itself:
struct A
{
~A() {}
};
or outside:
A::~A() {}
If the implementation is outside the class definition, but in a header, the methods have to be marked as inline
to prevent a multiple definition.
All used member methods need to be defined if used.
A common mistake is forgetting to qualify the name:
struct A
{
void foo();
};
void foo() {}
int main()
{
A a;
a.foo();
}
The definition should be
void A::foo() {}
static
data members must be defined outside the class in a single translation unit:
struct X
{
static int x;
};
int main()
{
int x = X::x;
}
//int X::x; //uncomment this line to define X::x
An initializer can be provided for a static
const
data member of integral or enumeration type within the class definition; however, odr-use of this member will still require a namespace scope definition as described above. C++11 allows initialization inside the class for all static const
data members.
@jave.web: While that does happen, the programmer usually notices that he has no
this
pointer and no access to class members. It’s quite rare to complete compilation and only fail during linking, when a non-static member function is missing its qualified-name.@jave.web: This was exactly my problem. Thank you! I am new to cpp, but as far as I can tell, I was having the exact problem that Ben Voigt says was quite rare. I think your solution would make a great answer.
@Snaptastic see stackoverflow.com/a/12574407/673730 – A common mistake is forgetting to qualify the name 🙂
They may be useful, just as are many answers to questions that are flagged as too general.
I would like to see minimal reproducible example as something we ask of most new users , honestly. I don’t mean anything by it, it is just – we can’t expect people to follow the rules we don’t inforce onto ourselves.
Show 2 more comments