Skip to main content
gamedev.net
🔒 Locked 🤖 Godot

Singleton template problem

Started by zalthar 4 replies 1.6k views
Original Post
zalthar
zalthar
I get these two link errors
Quote:
error LNK2019: unresolved external symbol "private: __thiscall ForceBase::ForceBase(void)" (??0ForceBase@@AAE@XZ) referenced in function "public: static class ForceBase * __cdecl Singleton::getInstance(void)" (?getInstance@?$Singleton@VForceBase@@@@SAPAVForceBase@@XZ) error LNK2019: unresolved external symbol "private: __thiscall GraphicsManager::GraphicsManager(void)" (??0GraphicsManager@@AAE@XZ) referenced in function "public: static class GraphicsManager * __cdecl Singleton::getInstance(void)" (?getInstance@?$Singleton@VGraphicsManager@@@@SAPAVGraphicsManager@@XZ) fatal error LNK1120: 2 unresolved externals
Here is the singleton.h file:

// =========================================================    
// This is a template class for handling singleton classes
//
// Author: Joakim Karlsson
// Version: 1.0
// Modified: 2004-11-03
// =========================================================

#ifndef Singleton_h
#define Singleton_h

// =================================================INCLUDES

// SYSTEM

// LOCAL

// =========================================================
template <typename T>
class Singleton
{
// ===================================================PUBLIC
public:

// ACCESS

    //
    // Get the Instance of the derived singleton class.
    //
    static T* getInstance()
    { 
        // Check if there is any T instance.
        if(mpInstance == 0)
        {
            // If not create one.
            mpInstance = new T;
        }
        
//        ASSERT(mpInstance != 0);

        return mpInstance; // Return the T instance.
    };

// OPERATIONS

    //
    // Deletes the instance.
    //
    static deleteInstance()
    {
        delete mpInstance;
        mpInstance = 0;
    };
	
// ==================================================PRIVATE
protected:
// SINGLETON
    static T* mpInstance;

    //
    // Default constructor. -SINGLETON-
    // Prohibits the user from creating more than one instance
    // of the derived class, by making the constructor PRIVATE.
    //    
    Singleton()
    {
    };

    
    //
    // Default destructor.
    //
    virtual ~Singleton()
    {
    };
};

// Static class member initialisation.
template <typename T> T* Singleton<T>::mpInstance = 0;

#endif // Singleton_h

Here is the Force.h file.

// =========================================================    
// This is the main "Force 3D Engine" class. This class is
// the first object to be created and the last to be 
// destroyed. You can get pointer to the other classes
// throught this class.
//
// Note: This class is a singleton class.
//
// Author: Joakim Karlsson
// Version: 0.1
// Modified: 2004-11-03
// =========================================================

#ifndef Force_h
#define Force_h

// =================================================INCLUDES

// SYSTEM

// LOCAL
#include "Singleton.h"
#include "GraphicsManager.h"

// =========================================================
class ForceBase : public Singleton<ForceBase>
{
// ===================================================PUBLIC
public:
    friend Singleton<ForceBase>;

// LIFECYCLE




// OPERATIONS
    
    

// ACCESS
	GraphicsManager* getGraphicsManager();

// INQUIRY



	 
// ==================================================PRIVATE
private:

    ForceBase();

    //
    // Default destructor.
    //
	~ForceBase();

// GAMELOOP


};

#endif // Force_h

The Force.cpp file:

// ===================================================PUBLIC

#include "Force.h"

// ACCESS

GraphicsManager* ForceBase::getGraphicsManager()
{
    return GraphicsManager::getInstance();
}

The GraphicsManager.cpp file:

// =========================================================    
// This is the main "Force 3D Engine" class. This class is
// the first object to be created and the last to be 
// destroyed. You can get pointer to the other classes
// throught this class.
//
// Note: This class is a singleton class.
//
// Author: Joakim Karlsson
// Version: 0.1
// Modified: 2004-11-03
// =========================================================

#ifndef GraphicsManager_h
#define GraphicsManager_h

// =================================================INCLUDES

// SYSTEM
#include <windows.h>

// LOCAL
#include "Singleton.h"

// =========================================================
class GraphicsManager : public Singleton<GraphicsManager>
{
// ===================================================PUBLIC
public:
    friend Singleton<GraphicsManager>;

// OPERATIONS
    bool doInit(HINSTANCE hInstance, int width, int height, bool windowed/*, D3DDEVTYPE deviceType*/);
    

// ACCESS
	


// INQUIRY



	 
// ==================================================PRIVATE
private:

    GraphicsManager();

    //
    // Default destructor.
    //
	~GraphicsManager();


// GAMELOOP


};

#endif // GraphicsManager_h

The GraphicsManager.h file:

// ===================================================PUBLIC

#include "GraphicsManager.h"

//
// WndProc
//
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	switch( msg )
	{
	case WM_DESTROY:
		::PostQuitMessage(0);
		break;
		
	case WM_KEYDOWN:
		if( wParam == VK_ESCAPE )
			::DestroyWindow(hwnd);
		break;
	}
	return ::DefWindowProc(hwnd, msg, wParam, lParam);
}

// OPERATIONS
bool GraphicsManager::doInit(HINSTANCE hInstance, int width, int height, bool windowed/*, D3DDEVTYPE deviceType*/)
{
	// Create the main application window.

	WNDCLASS wc;

	wc.style         = CS_HREDRAW | CS_VREDRAW;
	wc.lpfnWndProc   = WndProc; 
	wc.cbClsExtra    = 0;
	wc.cbWndExtra    = 0;
	wc.hInstance     = hInstance;
	wc.hIcon         = LoadIcon(0, IDI_APPLICATION);
	wc.hCursor       = LoadCursor(0, IDC_ARROW);
	wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wc.lpszMenuName  = 0;
	wc.lpszClassName = "Force";

	if( !RegisterClass(&wc) ) 
	{
		::MessageBox(0, "RegisterClass() - FAILED", 0, 0);
		return false;
	}
		
	HWND hwnd = 0;
	hwnd = ::CreateWindow("Force", "ForceApp", 
		WS_EX_TOPMOST,
		0, 0, width, height,
		0 /*parent hwnd*/, 0 /* menu */, hInstance, 0 /*extra*/); 

	if( !hwnd )
	{
		::MessageBox(0, "CreateWindow() - FAILED", 0, 0);
		return false;
	}

	::ShowWindow(hwnd, SW_SHOW);
	::UpdateWindow(hwnd);

	//
	// Init D3D: 
	//

	HRESULT hr = 0;

/*	// Step 1: Create the IDirect3D9 object.

	IDirect3D9* d3d9 = 0;
    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);

    if( !d3d9 )
	{
		::MessageBox(0, "Direct3DCreate9() - FAILED", 0, 0);
		return false;
	}

	// Step 2: Check for hardware vp.

	D3DCAPS9 caps;
	d3d9->GetDeviceCaps(D3DADAPTER_DEFAULT, deviceType, ∩︀);

	int vp = 0;
	if( caps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT )
		vp = D3DCREATE_HARDWARE_VERTEXPROCESSING;
	else
		vp = D3DCREATE_SOFTWARE_VERTEXPROCESSING;

	// Step 3: Fill out the D3DPRESENT_PARAMETERS structure.
 
	D3DPRESENT_PARAMETERS d3dpp;
	d3dpp.BackBufferWidth            = width;
	d3dpp.BackBufferHeight           = height;
	d3dpp.BackBufferFormat           = D3DFMT_A8R8G8B8;
	d3dpp.BackBufferCount            = 1;
	d3dpp.MultiSampleType            = D3DMULTISAMPLE_NONE;
	d3dpp.MultiSampleQuality         = 0;
	d3dpp.SwapEffect                 = D3DSWAPEFFECT_DISCARD; 
	d3dpp.hDeviceWindow              = hwnd;
	d3dpp.Windowed                   = windowed;
	d3dpp.EnableAutoDepthStencil     = true; 
	d3dpp.AutoDepthStencilFormat     = D3DFMT_D24S8;
	d3dpp.Flags                      = 0;
	d3dpp.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
	d3dpp.PresentationInterval       = D3DPRESENT_INTERVAL_IMMEDIATE;

	// Step 4: Create the device.

	hr = d3d9->CreateDevice(
		D3DADAPTER_DEFAULT, // primary adapter
		deviceType,         // device type
		hwnd,               // window associated with device
		vp,                 // vertex processing
	    &d3dpp,             // present parameters
	    device);            // return created device

	if( FAILED(hr) )
	{
		// try again using a 16-bit depth buffer
		d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
		
		hr = d3d9->CreateDevice(
			D3DADAPTER_DEFAULT,
			deviceType,
			hwnd,
			vp,
			&d3dpp,
			device);

		if( FAILED(hr) )
		{
			d3d9->Release(); // done with d3d9 object
			::MessageBox(0, "CreateDevice() - FAILED", 0, 0);
			return false;
		}
	}

	d3d9->Release(); // done with d3d9 object
	*/
	return true;
}

------------------------------- Zalthar -Joakim Karlsson------------------------------
Fruny
Fruny
Read the damned error message, it tells you precisely which functions you haven't implemented.
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
zalthar
zalthar
Read the damn code! The function is implemented in the Singleton class. Which the other classes derive from.
------------------------------- Zalthar -Joakim Karlsson------------------------------
Fruny
Fruny
So what? You redeclared it, you got to re-implement it. The singleton implements Singleton::Singleton(), not ForceBase::ForceBase().
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." — Brian W. Kernighan
Washu
Washu
Do tell, where in there have you bothered to DEFINE ForceBase::ForceBase()? How about GraphicsManager::GraphicsManager()?

Honestly, the error messages tell you exactly what's wrong.
In time the project grows, the ignorance of its devs it shows, with many a convoluted function, it plunges into deep compunction, the price of failure is high, Washu's mirth is nigh.
zalthar
zalthar
You where a realy friendly bunch of people. [flaming] If you have never seen this error before it might not be so damn easy!

But I solved it without your lacking help!
------------------------------- Zalthar -Joakim Karlsson------------------------------

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.