Why does the following code not give me a duplicate symbol linker error for Impl?
I ran across this problem in some code I inherited and I m recreating a shorter version here for simplicity.
I have two classes, Foo and Bar, that each define a different version of the same struct (Impl) in each of their .cpp files. So Foo.cpp and Bar.cpp each have an identically named Impl definition, but each one has a different inline constructor implementation.
Both Foo and Bar have a member variable of type Impl and each forward declares Impl in its .h file.
Foo.cpp news an instance of Bar inside its constructor. What s interesting is what gets created depends on the order the files are linked.
So this compilation command:
g++ -o a.out main.cpp Bar.cpp Foo.cpp
results in this output:
==> main()
Bar.cpp s Impl::Impl()
Bar.cpp s Impl::Impl()
<== main()
And this command:
g++ -o a.out main.cpp Foo.cpp Bar.cpp
results in this output:
==> main()
Foo.cpp s Impl::Impl()
Foo.cpp s Impl::Impl()
<== main()
I have tried this with gcc 4.1.2, Visual Studio 2008 and the Green Hills Multi 4.2.4 and they all produce the same result.
Foo.h
#ifndef FOO_H
struct Impl;
class Bar;
class Foo
{
public:
Foo();
~Foo();
private:
Impl* p;
Bar* bar;
};
#endif
Foo.cpp
#include <iostream>
#include "Foo.h"
#include "Bar.h"
struct Impl
{
Impl()
{
std::cout << "Foo.cpp s Impl::Impl()" << std::endl;
}
};
Foo::Foo()
: p(new Impl),
bar(new Bar)
{
}
Foo::~Foo()
{
delete p;
delete bar;
}
Bar.h
#ifndef BAR_H
#define BAR_H
struct Impl;
class Bar
{
public:
Bar();
~Bar();
private:
Impl* p;
};
#endif
Bar.cpp
#include <iostream>
#include "Bar.h"
struct Impl
{
Impl()
{
std::cout << "Bar.cpp s Impl::Impl()" << std::endl;
}
};
Bar::Bar()
: p(new Impl)
{
}
Bar::~Bar()
{
delete p;
}
main.cpp
#include <iostream>
#include "Foo.h"
int main (int argc, char const *argv[])
{
std::cout << "==> main()" << std::endl;
Foo* f = new Foo();
std::cout << "<== main()" << std::endl;
return 0;
}