Hi guys, I've run into the following annoying and seemingly incorrect behaviour in the Visual Studio 2008 C++ compiler:
Suppose I have a class library - Car.lib - that uses a "Car" class, with a header called "Car.h":
class Car
{
public:
void Drive()
{
Accelerate();
}
void Accelerate();
};
What I'm actually trying to do is use the Car headers (for some other functions), but without having to link with Car.lib itself (the actual class is not called "Car" but I am sanitising this example).
If I #include "Car.h" in the .cpp file used to build a managed C++ .dll, but never refer to Car, everything compiles and links fine. This is because I never instantiate a Car object.
However, the following:
namespace {
class Car
{
public:
Car(const Car& rhs)
{
Accelerate();
}
void Accelerate();
};
}
leaves me with the link error:
Error 2 error LNK2001: unresolved external symbol "public: void __thiscall `anonymous namespace'::Car::Accelerate(void)" (?Accelerate@Car@?A0xce3bb5ed@@$$FQAEXXZ) CREObjectWrapper.obj CREObjectBuilderWrapper
Note I've declared the whole thing inside an anonymous namespace so there's no way that the Car functions could be exported from the .DLL in any case.
I can categorically guarantee that Car is not referenced anywhere else, because I just made this class up and typed in the definition from scatch. The "real" class is a different name.
Declaring the copy constructor out-of-line makes no difference. i.e. the following also fails to link:
class Car
{
public:
Car(const Car& rhs);
void Accelerate();
};
Car::Car(const Car& rhs)
{
Accelerate();
}
It's something specifically to do with the copy constructor note, because the following, for example, does link:
class Car
{
public:
Car()
{
Accelerate();
}
void Accelerate();
};
I am not a C++ standards guru but this doesn't seem correct to me. Surely the compiler still should not have had to even generate any code that calls the Car copy constructor.
Can anyone confirm if this behaviour is correct? It's been a while since I used C++ - but I don't think this used to be an issue with Visual Studio 6.0 for example.
It might be because I am building a managed C++ .dll. (Later: yes, this is exactly the issue. The /clr option appears to introduce this dependency).
Here is the command line being used to build the project:
/OUT:"..\..\bin\Release\CREObjectBuilderWrapper.dll" /INCREMENTAL:NO /NOLOGO /LIBPATH:"..\..\lib\qa\lib" /LIBPATH:"..\..\lib\release" /LIBPATH:"..\..\lib\VDB" /DLL /MANIFEST /MANIFESTFILE:"Release\ObjectBuilderWrapper.dll.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"c:\Release\ObjectBuilderWrapper.pdb" /LTCG /DYNAMICBASE:NO /FIXED:No /MACHINE:X86 /KEYFILE:"c:\src\ObjectBuilderWrapper\\FI.snk" /ERRORREPORT:PROMPT CRERuntime.lib QA.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib
Can anyone suggest a workaround that allows one to "re-use" the Accelerate method from within the copy constructor and still have the copy constructor declared inline?