Sheesh. I've run into the infamous LNK2005
error when defining my class and I can't seem to place the issue.
(I'm tearing apart an equally infamous singleton of mine to reflect well, organization.) The initial said singleton was coded... ...in such a divergent, brilliant way... as to avoid all of the C++ OPP principles and concepts I was ignorant to at the time, but it worked! ....Somehow. Though some fluke of the simplest C++ concepts it did. Now I need organization, compilation speed, and advanced structuring techniques to make it work fast, and- you get it.
A-Anyway. After splitting it up, and having to rewrite some, I've noticed a necessity. I must declare multiple .cpp
files simply because the compiler is irked massively by double declarations, and the usual header class definitions.
Additionally I've used preprocessor directives accordingly as applicable. But something still remains wrong.
Note(Edit): I've rewritten the question to provide error given.
D3D.h
#include "Infinity.h"
class Direct3D :
public Infinity
{
public:
Direct3D();
~Direct3D();
IDXGISwapChain *Swapchain; //Display modes.
static ID3D11Device *Device;
static ID3D11DeviceContext *DeviceContext;
static ID3D11RenderTargetView *RenderTargetView;
void D3D_Start(float width, float height);
void D3D_Render();
void D3D_Terminate();
void ViewPort(float Height, float Width, float MaxDepth, float MinDepth, float TopLeftX, float TopLeftY);
}Direct3D;
...and Windows.h
#include "Infinity.h"
class Windows :
public Infinity
{
public:
Windows();
~Windows();
bool DisplayWindow(int width, int height, HINSTANCE hInstance);
static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
}Windows;
Finally, Infinity.h
#pragma once
class Infinity{
public:
Infinity();
~Infinity();
static HWND hWnd;
};
Whereas all implementations are in their respective .cpp files. Besides #pragma
, I've used #ifndef
... #endif
. I suspect that I may be inadvertently calling a kind of implementation by auto-initializing the classes in their header files. But it looks insanely kosher, and allows me to declare function members as:
Direct3D.D3D_Start()
without stating a static member, Direct3D::D3D_Start()
.
Should my headers all be static?
Edit: Below, the .cpp
file:
#include "stdafx.h"
#include "Infinity.h"
#include "Windows.h"
#include "Direct3D.h"
MSG msg;
float width = 1024;
float height = 768;
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
windows.DisplayWindow(1280, 900, hInstance);
direct3D.D3D_Start(width, height);
direct3D.ViewPort(height, width, 1.0f, 0.0f, 0, 0);
while (WM_QUIT != msg.message){
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
direct3D.D3D_Render();
}
}
direct3D.D3D_Terminate();
return msg.wParam;
}
*Update the .cpp
has been changed to show Niall's solution.
Edit:
Am I getting the LNK2005 issue because I auto-initialized my classes in their header files, considering the solution at Stack Overflow question:
VS 2010 C++ LNK2005 errors while using #pragma once and #ifndef
Which doesn't seem to work based my understanding of the solution.
VS2013 returns:
Error 1 error LNK2005: "class Direct3D Direct3D" (?Direct3D@@3V0@A) already defined in Direct3D.obj C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Win32Project3\Win32Project3.obj Win32Project3
Error 2 error LNK2005: "class Windows Windows" (?Windows@@3V0@A) already defined in Win32Project3.obj C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Win32Project3\Windows.obj Win32Project3
Error 3 error LNK1169: one or more multiply defined symbols found C:\Users\InfinityMachine\documents\visual studio 2013\Projects\Win32Project3\Debug\Win32Project3.exe 1 1 Win32Project3
You declare class Direct3D... } Direct3D;
and variable of the same name immediately. This would be the cause of such an error.
A variable of type Direct3D
, named Direct3D
(or otherwise) will be in each translation unit that includes that header, the same applies for Windows
.
One possible resolution is to remove the variable declaration, another would be to move it and make it static, or in an anonymous namespace. Alternates include extern
or implementing a singleton; which may be closer to the original intent.
Based on further discussions, an appropriate solution here is;
class Direct3D {};
extern Direct3D direct3D;
Then in the one of the implementation files
Direct3D direct3D;
This then declares the object as extern
and provides a single instance of it.