Problems with Absract Classes
I have a two classes one is abstract and another is inherited
Code:
// this is part of CGUI.h
class CGUI
{
public:
//other stuff
virtual void Init() = 0;
virtual void Paint() = 0;
};
Code:
//this is part of LoadScreen.h
#include "CGUI.h"
class LoadScreen : public CGUI
{
public:
virtual void Init();
virtual void Paint();
}
now in my definition of those classes I get problems
Code:
//this is part of LoadScreen.cpp
#include "LoadScreen.h"
void LoadScreen::Paint()
{
//stuff
}
void LoadScreen::Init()
{
//stuff
}
when I do this I get 2 errors
error LNK2001: unresolved external symbol "public virtual void __thiscall CGUI::Paint(void)" (?Paint@CGUI@@UAEXXZ)
error LNK2001: unresolved external symbol "public virtual void __thiscall CGUI::Init(void)" (?Init@CGUI@@UAEXXZ)
fatal error LNK1120: 2 unresolved externals
Re: Problems with Absract Classes
Based on the limited information you posted (which is obviously not enough to reproduce the problem), everything looks good. What Compiler (including version) are you using???
Re: Problems with Absract Classes
Not entirely certain how important it is, since it has been a while for abstract classes for me, but I do notice that you don't have a semicolon on the end of your Loadscreen.h
Re: Problems with Absract Classes
I'll post the whole header file if that makes a difference. I'm using Visual Studio 2005.
Code:
#ifndef LOADSCREEN_H
#define LOADSCREEN_H
#include "CGUI.h"
class CGUI;
class LoadScreen: public CGUI
{
public:
virtual void Init();
virtual void Paint();
///constructor
LoadScreen();
//destructor
~LoadScreen();
};
#endif LOADSCREEN_H
Code:
#ifndef CGUI_H
#define CGUI_H
#include "CommonInclude.h"
#include "EventReciver.h"
#define DO_NOT_EXIT -1
#define WINDOW_HEIGHT 640
#define WINDOW_WIDTH 480
class EventReciver;
class CGUI
{
public:
//variables
IrrlichtDevice* m_Device;
EventReciver* m_EventReciver;
s32 m_ExitCode;
//functions
virtual void Init() = 0;
virtual void Paint() = 0;
void Exit(s32 exitCode);
//constructor
CGUI();
//destructor
~CGUI();
};
#endif CGUI_H
Code:
//this is LoadScreen.cpp
#include "LoadScreen.h"
LoadScreen::~LoadScreen()
{
}
void onPlay(SEvent event, CGUI* source)
{
//stuff
}
void onOption(SEvent event, CGUI* source)
{
//stuff
}
void onHelp(SEvent event, CGUI* source)
{
//stuff
}
void onExit(SEvent event, CGUI* source)
{
//stuff
}
LoadScreen::LoadScreen()
{
}
void LoadScreen::Paint()
{
//stuff
}
void LoadScreen::Init()
{
// stuff
}
I can always post more code if necessay, but I don't think you all want to spend all day reading through everything. I thought I had everything necessary in the first post. But it is odd because I am using the open source Irrlicht Graphics Engine and it defines a class IEventReciver which is abstract and I overwrite it with EventReciver, but that doesn't seem to cause a problem when I implement its pure virtual functions.
Re: Problems with Absract Classes
I just skimmed through your code, but I noticed that you never defined (or at least, never showed us that you did) CGUI's constructor and destructor.
Re: Problems with Absract Classes
I suggest that you simplify to:
Code:
#ifndef LOADSCREEN_H
#define LOADSCREEN_H
#include "CGUI.h"
class LoadScreen : public CGUI
{
public:
virtual void Init();
virtual void Paint();
///constructor
LoadScreen();
//destructor
~LoadScreen();
};
#endif
Code:
#ifndef CGUI_H
#define CGUI_H
class CGUI
{
public:
virtual void Init() = 0;
virtual void Paint() = 0;
//destructor
virtual ~CGUI() {}
};
#endif
Code:
//this is LoadScreen.cpp
#include "LoadScreen.h"
LoadScreen::~LoadScreen()
{
}
LoadScreen::LoadScreen()
{
}
void LoadScreen::Paint()
{
}
void LoadScreen::Init()
{
}
Then test with:
Code:
#include <memory>
#include "CGUI.h"
#include "LoadScreen.h"
int main()
{
LoadScreen screen;
screen.Paint();
screen.Init();
std::auto_ptr<CGUI> gui(new LoadScreen);
gui->Paint();
gui->Init();
}
Note that CGUI's destructor should be declared virtual since it is a base class.
Re: Problems with Absract Classes
I got the link errors to go away by adding a body for the two virtual functions. Now I don't want to use the Paint and Init functions I defined right there. I want to use the init and paint functions I define in the derived class. When I take away those lines I get the linker errors
Code:
#include "CGUI.h"
CGUI::~CGUI()
{
this->Exit(0);
}
CGUI::CGUI()
{
m_ExitCode = DO_NOT_EXIT;
m_EventReciver = new EventReciver();
m_Device = createDevice(video::EDT_OPENGL,core::dimension2d<s32>(WINDOW_HEIGHT,WINDOW_WIDTH),16,false,true,true,m_EventReciver);
if(m_Device == 0)
{
printf("\nFatal Error: Device could not be created\n");
this->Exit(1);
}
else{
video::IVideoDriver* driver = m_Device->getVideoDriver();
gui::IGUIEnvironment* env = m_Device->getGUIEnvironment();
Init();
while(m_Device->run() && driver)
{
if(m_ExitCode != DO_NOT_EXIT)
{
break;
}
else if (m_Device->isWindowActive())
{
driver->beginScene(true, true,video::SColor(255,255,255,255));
Paint();
driver->endScene();
}
}
}
}
void CGUI::Exit(s32 exitCode)
{
m_ExitCode = exitCode;
}
void CGUI::Paint(){}
void CGUI::Init(){}
Re: Problems with Absract Classes
Quote:
I got the link errors to go away by adding a body for the two virtual functions.
Have you tried out my minimal example? I did not need to turn the pure virtual functions into ordinary virtual functions, yet I did not get any linker errors when I tested.
Re: Problems with Absract Classes
I did try your test, however it did not work, but I just figured out why. In the constructor for CGUI I made a call to Init and Paint, however they were defined as pure virtual functions so it gave me a linker error. How can I call those functions and just get whatever the base class defines them as?
Re: Problems with Absract Classes
Quote:
Originally Posted by BossOfTheGame
I did try your test, however it did not work,
So the test that was posted as-is by laserlight didn't work, or it did work?
Quote:
but I just figured out why. In the constructor for CGUI I made a call to Init and Paint
If they are unimplemented, you can't call them without a linker error.
Regards,
Paul McKenzie
Re: Problems with Absract Classes
Quote:
In the constructor for CGUI I made a call to Init and Paint, however they were defined as pure virtual functions so it gave me a linker error. How can I call those functions and just get whatever the base class defines them as?
Do not call virtual functions (pure or otherwise) in constructors. They will probably not do what you expect.
Read: When my base class's constructor calls a virtual function on its this object, why doesn't my derived class's override of that virtual function get invoked?
EDIT:
Oh wait, you wanted to "just get whatever the base class defines them as". In that case obviously they cannot be pure virtual, and you will get what you expect when you call them in the base class constructor.