Thread: Static class?

  1. #1
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607

    DirectInput problems

    I'm currently working on mouse support for my tile engine and I've run into problems. The DirectInput object is one interface - created one time. The Mouse interface is as well but I'm deriving it from DirectInput. Problem is that when I create the mouse, keyboard, etc - I do not want to create another instance of DirectInput.

    If I declare DXInput as static, will this work?
    It seems that MSVC does not like that, but I thought this was possible with classes?


    Here is my setup:

    DXInput.h
    Code:
    #ifndef _DXINPUT_
    #define _DXINPUT_
    
    #define DIRECTINPUT_VERSION 0x0700
    #include "dinput.h"
    
    class DXInput
    {
      protected:
        LPDIRECTINPUT lpdi;
      public:
        DXInput(HINSTANCE instance);
        ~DXInput(void) {if (lpdi) lpdi->Release();};
    };
    
    #endif
    DXInput.cpp
    Code:
    #include "DXInput.h"
    
    DXInput::DXInput(HINSTANCE instance)
    {
    	
      if (FAILED(DirectInputCreate(instance,DIRECTINPUT_VERSION,&lpdi,NULL)))
      {
        //error
      }
    }
    DXMouse.h
    Code:
    #ifndef _DXMOUSE_
    #define _DXMOUSE_
    
    #include "DXInput.h"
    
    #define RMB 0
    #define LMB 1
    #define MMB 2
    
    class DXMouse:public DXInput
    {
      LPDIRECTINPUTDEVICE lpdiMouse;
      DIMOUSESTATE MouseState;
      public:
        DXMouse(void) {};
        ~DXMouse(void) 
        {
            if (lpdiMouse) lpdiMouse->Unacquire();
            if (lpdiMouse) lpdiMouse->Release();
        }
        void Query(void) {if (FAILED(lpdiMouse->GetDeviceState(sizeof(DIMOUSESTATE),(LPVOID)MouseState))) };
        int CheckButton(int ButtonToCheck);
        void Show(void);
        void Hide(void);
        DIMOUSESTATE GetMouseState(void) {return MouseState;};
    };
    #endif
    DXMouse.cpp
    Code:
    #include "DXInput.h"
    #include "DXMouse.h"
    
    DXMouse::DXMouse(void)
    {
        if (FAILED(lpdi->CreateDevice(GUID_SysMouse,&lpdiMouse,NULL))
       {
         //error
       }
       if (FAILED(lpdiMouse->SetCooperativeLevel(MainWindow,DISCL_BACKGROUND | DISCL_NONEXCLUSIVE)))
      {
        //error
      }
      if (FAILED(lpdiMouse->SetDataFormat(&c_dfDIMOUSE)))
      {
        //error
      }
      if (FAILED(lpdiMouse->Acquire()))
      {
        //error
      }
    }
    
    int DXMouse::CheckButton(int ButtonToCheck)
    {
      Query();
      if (MouseState.rgbButtons[ButtonToCheck] & 0x80)
      {
         return TRUE;
      } else return FALSE;
    }
    Any help would be appreciated. I really want the mouse to be accessible by everyone in the engine. Having to go through a bunch of inheritance crapola when the mouse is a pretty global object seems kinda dumb.

    Right now the compiler is yelling at me about a default constructor for DXInput when I attempt to create the mouse - I understand why it's doing this, but I'm not sure about the best route to go in getting around it.

    And hey, look, all that and no assembly at all.
    Last edited by VirtualAce; 12-21-2003 at 02:44 AM.

  2. #2
    Registered User glUser3f's Avatar
    Join Date
    Aug 2003
    Posts
    345
    I had a similar problem when working on the design of my 3D engine, finally I decided to go with global variables, something like this:
    Code:
    //dxinput.h
    //...
    extern DXInput* gDXInput;
    //..
    when the engine starts, it creates gDXInput (among the others) and when it shuts down, gDXInput is deleted.
    I highly recommend against static variables, you may end up with mysterious errors when shutting down, and later discover that some variables are deleted before others.

  3. #3
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    If you want 1 version of the DirectInput interface, and want it available across a number of different objects then you might want to lookup the singleton pattern.

    It's kind of like a static global option, but with more control and you can also decide how the object should be created/destroyed. You basically give an object a private contructor and a static function to either create itself or pass a reference of itself. Then to access the object's reference, you call this function

    I wont give you a simple example because there's lots of slighty different ways of doing it and it's well worth a read. Scott Meyers does some good work on it and there are a few resources on the web

  4. #4
    Registered User
    Join Date
    Sep 2003
    Posts
    25
    Deriving the mouseclass from the inputclass doesnīt seem like a good idea to me, since it as you said does create a new directinput object.

    One way to deal with it could be to put the mouse and the keyboard class into the inputclass.

    Another is to put a public function in the inputclass that returns the pointer to lpdi (which itself is a pointer). If you donīt want the function public declare it as private and make the mouse and keyboardclass friends to the inputclass.

  5. #5
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    I changed my mind about the example...here's a very quick rough example;

    Code:
    #include <iostream>
    
    class SomeInterface
    {
    public:
    	void SomeFunc(){std::cout << "You made an interface call!!" << std::endl;}
    };
    
    class InterfaceSingleton
    {
    	InterfaceSingleton()
    	{
    		try
    		{
    			lpsi = new SomeInterface;
    			std::cout << "**Object Created**" << std::endl;
    		}
    		catch(...)
    		{
    			//handle
    		}		
    	}
    	~InterfaceSingleton()
    	{
    		delete lpsi;
    		std::cout << "**Object Dead**" << std::endl;
    	}
    	SomeInterface *lpsi;
    public:
    	SomeInterface *GetInterface(){return lpsi;}
    	static InterfaceSingleton& GetSingleton();
    };
    
    InterfaceSingleton& InterfaceSingleton::GetSingleton()
    {
    	static InterfaceSingleton is;
    	return is;
    }
    
    
    int main()
    {
    	std::cout << "Before the call no object is created, now I make a call;" << std::endl;
    	InterfaceSingleton::GetSingleton().GetInterface()->SomeFunc();
    	std::cout << "I make a call again, but this time no new object" << std::endl;
    	InterfaceSingleton::GetSingleton().GetInterface()->SomeFunc();
    	std::cout << "This is after the calls are made. Now the compiler will destroy my singleton" << std::endl;
    }

  6. #6
    Registered User glUser3f's Avatar
    Join Date
    Aug 2003
    Posts
    345
    singleton classes caused me a lot of troubles, I had several singleton classes, a texture manager, and a shader manager, shader manager needed texture manager for its operations, on shut down, and for some reason, texture manager destructor was always called before shader manager, later, when shader manager destructor was called, it caused acess violation because it tried to access texture manager.

    This is why I recommend global pointers allocated with new.

  7. #7
    &TH of undefined behavior Fordy's Avatar
    Join Date
    Aug 2001
    Posts
    5,793
    Originally posted by glUser3f
    singleton classes caused me a lot of troubles, I had several singleton classes, a texture manager, and a shader manager, shader manager needed texture manager for its operations, on shut down, and for some reason, texture manager destructor was always called before shader manager, later, when shader manager destructor was called, it caused acess violation because it tried to access texture manager.

    This is why I recommend global pointers allocated with new.
    And if you had reserched singletons more you would notice a number of models that allowed you to destroy each individual object at a time of your choosing.

    That's why I recommended reading....there's good stuff out there on this subject

  8. #8
    Registered User glUser3f's Avatar
    Join Date
    Aug 2003
    Posts
    345
    Originally posted by Fordy
    And if you had reserched singletons more you would notice a number of models that allowed you to destroy each individual object at a time of your choosing.

    That's why I recommended reading....there's good stuff out there on this subject
    Hmm, there maybe a good way to destroy the instance when needed, but wouldn't a global variable make stuff much simpler?
    I mean, which one do you prefer to access the instance:
    Code:
    gDXInput->checkMouse();
    or
    Code:
    DXInput::getInstance()->checkMouse();
    on the other hand, singleton classes work better in projects with several developers.
    so you choose...

  9. #9
    Registered User VirtualAce's Avatar
    Join Date
    Aug 2001
    Posts
    9,607
    Thanks all for your help. I'm leaning more towards simply making the LPDIRECTINPUT object global. I'm gaining nothing by placing it in a class and it really does not need to be encapsulated.

    I will leave the mouse in a class but it will use the LPDIRECTINPUT global interface to DirectInput. Just seems simpler that way.

    Probably going to do the same with my DirectSound interface.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Getting other processes class names
    By Hawkin in forum Windows Programming
    Replies: 3
    Last Post: 03-20-2008, 04:02 PM
  3. Static member of a class
    By Gravedigga in forum C++ Programming
    Replies: 2
    Last Post: 08-15-2005, 03:54 AM
  4. structure vs class
    By sana in forum C++ Programming
    Replies: 13
    Last Post: 12-02-2002, 07:18 AM
  5. Replies: 3
    Last Post: 10-10-2002, 07:34 AM