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;
}