c++ Setting a pointer variable in parent class from child and use it in parent class
i'm sorry for the title. I seem to have a problem. I'm just a beginner and i'm sorry if this was asked before.. i couldnt find a straight answer on this one. (when i search class, pointer and child i get results about passing parent or child pointers...开发者_开发技巧 i do not want to pass the (this) child or parent pointer, i just want to pass a pointer i initialized on a child class.. to the parent). What i'm trying to do here is better explained by code:
class App
{
public:
virtual void init(void) { window = &BasicWindow(); }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = &OpenGLWindow(); }
};
int main ()
{
App *game = &Game();
game->init();
game->createWindow();
return 0;
}
Is this legal?
I have an abstract Window class from which BasicWindow and OpenGLWindow derives.
However, when i create the window i get an Access violation reading location
error breaking at window->create()
inside the App::createWindow()
function.
Thanks
I'm guessing this is because you are pointing to a temporary:
window = &BasicWindow()
Once that function exits, window
points to "crap" and bad things will happen.
presumably, what you want to do is to create a new instance of the window - i.e.
window = new BasicWindow();
Don't forget to cleanup!
I'm going to take a punt that you're coming from Objective-C? ;)
I think your problems all stem from not understanding how C++ objects are created.
First up: window = &BasicWindow();
is not how you should be creating a new object. You need to use window = new BasicWindow;
This results in space for a BasicWindow being allocated in memory, and the default constructor for BasicWindow will be invoked.
Your have a similar error in your main() method, however in this case you do not need to use new to allocate it, you can just declare an instance and it will be created on the stack.
Your main method would then look like:
int main ()
{
Game game;
game.createWindow();
return 0;
}
The remaining problem is that your init methods are not being called. In C++ constructors are called automatically, and are named the same name as the class. An example default constructor for the game class would be:
Game() { window = new OpenGLWindow(); }
Another thing you need to know is that, unlike objective C, the entire hierarchy of constructors is called automatically when you create an object. That is, when you create an instance of Game, its constructor is called, as well as the constructor of every base class. In fact, the base class constructor is called FIRST. So in your case, if you just change the init methods to constructors, you'll allocate two windows (one of each type) and leak the BasicWindow. Which is not cool.
You should probably just leave them named init, and just make sure you call it immediately after creation.
In summary, try this:
class App
{
public:
virtual void init(void) { window = new BasicWindow; }
virtual void createWindow(void) { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init(void) { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
(and don't forget to cleanup the new'd objects!)
EDIT (added example complete with cleanup):
class App
{
public:
App() : window( NULL ) {}
virtual ~App() { delete window; }
virtual void init() { window = new BasicWindow; }
virtual void createWindow() { window->create(); }
protected:
Window *window;
};
class Game : public App
{
public:
virtual void init() { window = new OpenGLWindow; }
};
int main ()
{
Game game;
game.init();
game.createWindow();
return 0;
}
window
is an uninitialized pointer of class App
. Because, no where you are calling init
method. So, window->create()
results error, when base class createWindow()
is called.
Edit 1:
As far as now, every thing is syntactically correct but amn't sure of what you are trying to achieve. Don't create temporary/nameless objects and assign them. Instead construct them with operator new
in window = &BasicWindow();
and window = &OpenGLWindow();
. Since the class manages resources, you should follow the principle Rule of Three. Also know that in statement -
App *game = new Game();
The static type of operand ( App* ) is different from the dynamic type( Game*). In such a case, the static type acts as a base class and it's destructor must be virtual or else the behaviour is undefined. So, the App class destructor must be virutal.
The error might be related to the fact that you are using pointers to temporaries.
virtual void init(void) { window = &BasicWindow(); }
This pointer becomes invalid after the ";". Use "new" instead of "&". You need to call game->init() if you want to use the window pointer too (Even better put in in a constructor, thats what they are for).
Besides that, it is perfectly legal to change protected members of base classes.
精彩评论