Sign in to follow this  

extern ClassName* const &InterfaceName ?

This topic is 4863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I'm trying to find a decent way to allow access to an engine-type class without leaving the pointer globally accessable to modification. Here is an example of my best solution:
// Screen.h file
class Screen
{
};
extern Screen* const &ScreenPtr;
 
// Screen.cpp file
Screen *RealInstance = NULL;
Screen* const &ScreenPtr = RealInstance;


The screen.cpp file is free to allocate and destroy the real instance memory, but other modules are hidden from this privilege, correct? And the reference is protected from any modification, with the const setting, right? Is this a bad way to do this? I'm trying to avoid the whole GetInstance()->DoSomething() deal, mainly because I think it just confuses things and looks very ugly. I would appreciate any ideas on how this can backfire on me, or any problems down the road that I cannot predict. Is there any reason this is a bad design? Also, are there any performance issues with this? Accessing a reference is no different than accessing it's actual pointer, correct? It doesn't have to do two address lookups or anything, right? Thanks for any help.

Share this post


Link to post
Share on other sites
Well, your declaration needs to be atleast a const class* to prevent delete being called on it, because delete doesn't change the value of the pointer, but the object pointed to. So you probably want const screen* const, which will obviously prevent you calling some member functions, etc. Now you're back at the start.

Share this post


Link to post
Share on other sites
Damn, you're totally right. So it protects against everything except delete? I guess it is very difficult to accidently call delete on such things, and delete can even be called on a GetInstance() type return value, right? The only way I can see to totally protect it is to find a way to avoid the use of a pointer altogether. Is that possible?

Alpha_ProgDes -> How can I allocate the instance dynamically and have a reference to the actual allocation memory?

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
Damn, you're totally right. So it protects against everything except delete? I guess it is very difficult to accidently call delete on such things, and delete can even be called on a GetInstance() type return value, right? The only way I can see to totally protect it is to find a way to avoid the use of a pointer altogether. Is that possible?

Couldn't you just make the class's destructor private?
Seems to bring protection to ridicilous levels though, so I'd suggest that you find a simple solution. Or you could just skip the protection completely, there's generally so many other (and much more common) mistakes you can make if you don't know the library that I don't think you should spend much time on idiot-proofing this one.

Share this post


Link to post
Share on other sites
You're saying I should drop the whole thing and just declare the pointer as normal extern? Or I should just not bother protecting it from being deleted?

I would like to at least protect it from being altered by misc typos. Something stupid and simple, such as if(Screen = NULL) OuchThatHurts().

Thanks for the suggestion.

Share this post


Link to post
Share on other sites
Doesn't that have the same flaw, though? The ability to delete the pointer memory from the accessor function?

It's just a personal thing I have againt accessors and instances. For a class instance, I can deal with it. But a global instance, it just seems very ugly to me. GetClass()->RunMethod(). If I make an accessor function, I'd probably declare a macro to remove the Get and () from it anyways.

That doesn't mean I won't use it. I'd just rather not. Would using a const reference be considered a less-attractive method?

Share this post


Link to post
Share on other sites
Protecting a dynamic object from being deleted is something you won't be able to do, and rightly so. Ordinarily, you would overload the operator privately, or just not define it, but since you are using new, you need delete.

Seriously, you're making a mountain out of a mole hill. Only malicious coders would delete the variable to begin with. The 'correct' design pattern would, IMHO, not rely on globals to begin with, so cast your doubts into the void and continue the good battle. [I got carried away at the end...] [wink]

Share this post


Link to post
Share on other sites
Well, the possibility of deleting it is very low. I'm more concerned about just protecting from typos or other unseen mistakes. I wouldn't need a reference if I could make the pointer itself const. But of course I can't do that.

The only way I could avoid globals is to declare some God class to encapsulate everything. I'd still be stuck with the same problems. Accessor functions :)

As long as this method isn't frowned upon, I'm happy.

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
Well, the possibility of deleting it is very low. I'm more concerned about just protecting from typos or other unseen mistakes. I wouldn't need a reference if I could make the pointer itself const. But of course I can't do that.

Of course you can. Here.


// someFile.h
Screen const* getScreenPtr();

// someFile.cpp
Screen *myInstance;
Screen const* getScreenPtr() { return myInstance; }

Share this post


Link to post
Share on other sites
Quote:
Original post by Jiia
Damn, you're totally right. So it protects against everything except delete? I guess it is very difficult to accidently call delete on such things, and delete can even be called on a GetInstance() type return value, right? The only way I can see to totally protect it is to find a way to avoid the use of a pointer altogether. Is that possible?

Alpha_ProgDes -> How can I allocate the instance dynamically and have a reference to the actual allocation memory?


Well one possiable way could be:


#include <iostream>

class Screen {

const int _j;

public:

Screen(int i = 0): _j(i) {}

const int& j() const { return _j; }

};

//declare
extern const Screen jim;

//define
const Screen jim(30);

const Screen& screen() { return jim; }

int main() {

std::cout << screen().j() << std::endl;

return 0;
}




There is one problem with it (i think?) is the problem associated with the order of static allocation/intialization.

Another way could be to instantiate on the heap but use a constant smart pointer (say boost smart pointers) to constant data, then have a function like the above that returns a constant reference or a constant smart pointer to constant data e.g.


#include <boost/smart_ptr.hpp>
#include <iostream>

class Screen {

const int _j;

public:

Screen(int i = 0): _j(i) {}

const int& j() const { return _j; }

};


typedef const boost::shared_ptr<const Screen> const_screen_ptr;

//declare
extern const_screen_ptr jim;

//define
const_screen_ptr jim(new const Screen(30));

const Screen& screen() { return (*jim); }
const_screen_ptr screen_ptr() { return jim; }

int main() {

std::cout << screen().j() << std::endl;
std::cout << screen_ptr()->j() << std::endl;

return 0;
}



EDIT: Probably not a good idea to intialize "jim" like that thou

Share this post


Link to post
Share on other sites

This topic is 4863 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this