Creating a SimObject
by William Todd Scott · in Torque Game Engine · 11/05/2005 (7:20 pm) · 13 replies
Hi,
I am trying to create a C++ class that can be access from script.
So, I am inheriting from SimObject and I followed the documentation but I am getting the following error:
error C2248: 'ConsoleObject::consoleInit' : cannot access private member declared in class 'CMyClass'
Can anyone point me in the right direction?
Thanks
Todd
I am trying to create a C++ class that can be access from script.
So, I am inheriting from SimObject and I followed the documentation but I am getting the following error:
error C2248: 'ConsoleObject::consoleInit' : cannot access private member declared in class 'CMyClass'
Can anyone point me in the right direction?
Thanks
Todd
#2
I think my problem is that the class I am trying to create is a singleton. I believe that all SimObjects are instantiated by the engine once at startup in order to handle their persistent fields. My singleton class has a private constructor.
Thanks
Todd
11/05/2005 (7:50 pm)
Hey Rubes,I think my problem is that the class I am trying to create is a singleton. I believe that all SimObjects are instantiated by the engine once at startup in order to handle their persistent fields. My singleton class has a private constructor.
Thanks
Todd
#3
As far as a stab in the dark, 2 things come to mind. Is the method that you are trying to access in the public area of your class? Also, there are some functions like this one from player.cc
11/06/2005 (8:23 pm)
Could you post some code? I'm a noob myself, but I've been working quite a bit with ConsoleMethod and addVariable, and I seem to recall getting that error. But I can't recall off the top of my head what I did to solve it :(As far as a stab in the dark, 2 things come to mind. Is the method that you are trying to access in the public area of your class? Also, there are some functions like this one from player.cc
DECLARE_CONOBJECT(Player);I'm not 100% of what they do, but declaring it in the public sector of your class might help solve your problem. Sorry I couldn't be of more help.
#4
Thanks for the response.
It was indeed the fact that my class was a singleton. I believe the engine instatiates all SimObject classes at startup in order to handle persistent fields. Since my constructor was private it couldn't instantiate my class. Once I removed the strict singleton access, it worked fine.
Thanks
Todd
11/07/2005 (7:04 am)
Hey Noah,Thanks for the response.
It was indeed the fact that my class was a singleton. I believe the engine instatiates all SimObject classes at startup in order to handle persistent fields. Since my constructor was private it couldn't instantiate my class. Once I removed the strict singleton access, it worked fine.
Thanks
Todd
#5
11/07/2005 (8:13 am)
I had to do a google search to figure out what singleton means ;) If I had known, then I would have realized that your constructor was intentionally in the private section. I found this quote:Quote:The Singleton design pattern is used to represent an object in a situation where only a single instance of that object can exist. Situations where this might arise include objects representing null or empty, centralized broker objects, centralized accumulator objects, etc.and unfortunately I don't really get what that means. I would really appreciate it if you'd take a second to explaing what need might arise in Torque that would cause you to consider using a singleton.
#6
11/08/2005 (1:19 am)
It's a really fancy global variable that ensures only one instance of a class exists.
#8
11/08/2005 (7:50 am)
Thanks for the replies. I'm curious, could you create a singleton class without exposing it to the console, then derive a class from it with a public constructor and expose the console methods there? Obviously I don't know what the rules for deriving from a singleton are, nor do fully understand the requirements of the engine to initialize the console, but on the surface it seems like that might work.
#9
The whole idea of the singleton is to only allow an instance of it to be created through a call to one of its static member functions. This static member function also checks to see if an instance of the object alread exists, and if it does it returns that instance without creating a new one.
Torque needs to be able to create an instance of every console object.
However, you can ensure that only a single object is created without using the singleton pattern. I believe Torque does exactly that with the DemoGame class.
Thanks.
Todd
11/08/2005 (8:34 am)
No,The whole idea of the singleton is to only allow an instance of it to be created through a call to one of its static member functions. This static member function also checks to see if an instance of the object alread exists, and if it does it returns that instance without creating a new one.
Torque needs to be able to create an instance of every console object.
However, you can ensure that only a single object is created without using the singleton pattern. I believe Torque does exactly that with the DemoGame class.
Thanks.
Todd
#10
Did you solve this problem? I have several SimObjects that are really supposed to be true Singletons.
By making propper use of SimObject functionality and with some carefull programming I've mimized the issue. However I can't find a bullet-proof, idiot proof way to ensure the class will only ever be instantiated once - for the reasons you listed above.
I'm going to look at the DemoGame class per your suggestion, but if you have a solution I'd like to hear it!
Thanks,
Raven
02/26/2006 (7:13 pm)
Todd,Did you solve this problem? I have several SimObjects that are really supposed to be true Singletons.
By making propper use of SimObject functionality and with some carefull programming I've mimized the issue. However I can't find a bullet-proof, idiot proof way to ensure the class will only ever be instantiated once - for the reasons you listed above.
I'm going to look at the DemoGame class per your suggestion, but if you have a solution I'd like to hear it!
Thanks,
Raven
#11
I did not find a bullet-proof solution, but I also tried to minimize the problem.
I simply took my singleton class, made my the constructor public, set the static pointer if the constructor is called, and put an error message and an assert statement in the constructor for the case where the static pointer is not null.
So, the "normal" access to the class remains a static member function. If an object is created via a "new" statement AND an object already exists, an error is posted and the program asserts.
I found this to be a reasonable, if far from bullet-proof, solution.
Todd
02/26/2006 (7:41 pm)
Hey Raven,I did not find a bullet-proof solution, but I also tried to minimize the problem.
I simply took my singleton class, made my the constructor public, set the static pointer if the constructor is called, and put an error message and an assert statement in the constructor for the case where the static pointer is not null.
So, the "normal" access to the class remains a static member function. If an object is created via a "new" statement AND an object already exists, an error is posted and the program asserts.
I found this to be a reasonable, if far from bullet-proof, solution.
Todd
#12
Thanks for the quick reply!
I was centering in on the same idea but when I finally tried it, having to call a 'getInstance()' function interfered with trying to setup the object in my *.mis file.
I'm trying a (new?) variation on that theme. Since the object is going to be a registered SimObject anyways, I 've decided I don't need 'getInstance()' to keep track of it. My latest idea is somthing like this:
Of coruse the Constructor is still public in this case. This seems to be working for now.
Thanks for the help!
02/27/2006 (6:01 pm)
Todd,Thanks for the quick reply!
I was centering in on the same idea but when I finally tried it, having to call a 'getInstance()' function interfered with trying to setup the object in my *.mis file.
I'm trying a (new?) variation on that theme. Since the object is going to be a registered SimObject anyways, I 've decided I don't need 'getInstance()' to keep track of it. My latest idea is somthing like this:
//---------------------------------------------------------------------------
// Begin Class: TaskManager
//---------------------------------------------------------------------------
// initilize static variable 'sInstance' (now sTaskManager) to NULL
TaskManager* TaskManager::sTaskManager = 0;
//---------------------------------------------------------------------------
/// Function name: TaskManager::TaskManager
/// Summary: Default Constructor
//---------------------------------------------------------------------------
TaskManager::TaskManager()
{
// Make sure there are no existing instances
assert( sTaskManager == 0 );
sTaskManager = this;
} // End constructor for: TaskManager
//---------------------------------------------------------------------------
/// Function name: TaskManager::~TaskManager
/// Summary: Default Destructor
//---------------------------------------------------------------------------
TaskManager::~TaskManager()
{
// Release Singleton
sTaskManager = 0;
} // end constructor for: TaskManagerOf coruse the Constructor is still public in this case. This seems to be working for now.
Thanks for the help!
#13
Yeah, that looks almost identical to what I did. I'm not sure why the getInstance() would be a problem, but if you don't need it...
The only thing I added was a console warning in addition to the assert. That way, if a problem somehow makes it all the way to the release version (where the assert won't exist), you will still have some clue as to why the program is misbehaving.
Best,
Todd
02/27/2006 (7:41 pm)
Hey Raven,Yeah, that looks almost identical to what I did. I'm not sure why the getInstance() would be a problem, but if you don't need it...
The only thing I added was a console warning in addition to the assert. That way, if a problem somehow makes it all the way to the release version (where the assert won't exist), you will still have some clue as to why the program is misbehaving.
Best,
Todd
Torque 3D Owner Rubes