Extending a class with pure virtual functions

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

Extending a class with pure virtual functions

Post by ajtgarber »

My compiler is bitching about not being able to allocate an instance of MyGame because some of its methods are pure virtual, I've given the methods definitions in the subclass but it doesn't seem to care.

Game.h

Code: Select all

#pragma once

#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

//Abstract class
class Game {
private:
	int requestedFPS;
	int reportedFPS;
	SDL_Surface* screen;
	int width;
	int height;
	
public:
	Game(int width, int height);
	virtual ~Game();
	
	virtual void update() const = 0;
	virtual void render() const = 0;
	virtual void init() const = 0;
	
	virtual void keyEvent(int event, int key) const = 0;
	virtual void mouseEvent(int event, int x, int y, int button) const = 0;
	
	int getRequestedFPS();
	int getReportedFPS();
	
	void setRequestedFPS(int requestedFPS);
	void setReportedFPS(int reportedFPS);
	
	int getWidth();
	int getHeight();
};
MyGame.h

Code: Select all

#pragma once

#include "Game.h"

class MyGame : public Game {
public:
	MyGame(int width, int height);
	
	virtual void init();
	virtual void update();
	virtual void render();
	
	virtual void keyEvent(int event, int key);
	virtual void mouseEvent(int event, int x, int y, int button);
};
main.cpp

Code: Select all

#include <iostream>
#include <SDL/SDL.h>
#include <SDL/SDL_opengl.h>

#include "FBEngine.h"
#include "Game.h"
#include "MyGame.h"

using namespace std;

int main(int argc, char* argv[]) {
	MyGame *game = new MyGame(640, 480);
	FBEngine *engine = FBEngine::getInstance();
	engine->setGame(game);
	engine->start();
	
	delete game;
	return 0;
}
User avatar
Ginto8
ES Beta Backer
ES Beta Backer
Posts: 1064
Joined: Tue Jan 06, 2009 4:12 pm
Programming Language of Choice: C/C++, Java

Re: Extending a class with pure virtual functions

Post by Ginto8 »

I'd need to see the FBengine class (more specifically the setGame method) and the exact error message before I can give you an answer. From the code given, it seems perfectly fine.
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

Re: Extending a class with pure virtual functions

Post by ajtgarber »

FBEngine.h

Code: Select all

#pragma once

#include <SDL/SDL_opengl.h>
#include <SDL/SDL.h>
#include <ctime>

#include "Game.h"

#define FBE_MOUSE_MOVED 0
#define FBE_MOUSE_PRESSED 1
#define FBE_MOUSE_RELEASED 2

#define FBE_KEY_PRESSED 0
#define FBE_KEY_RELEASED 1

class FBEngine {
private:
	Game* game;
	bool running;
	
public:
	static inline FBEngine* getInstance() {
		static FBEngine* instance;
		if(instance == NULL) {
			instance = new FBEngine();
		}
		return instance;
	}
	
	FBEngine();
	virtual ~FBEngine();
	
	void setGame(Game* game);
	Game* getGame();
	
	bool isRunning();
	void setRunning(bool running);
	
	void start();
};
FBEngine.cpp

Code: Select all

/*
 *  FBEngine.cpp
 *  SDLOpenGLTest
 *
 *  Created by Ajtgarber on 8/15/10.
 *  Copyright 2010 __MyCompanyName__. All rights reserved.
 *
 */

#include "FBEngine.h"

FBEngine::FBEngine() : running(false) {

}

FBEngine::~FBEngine() {

}

void FBEngine::setGame(Game* game) {
	this->game = game;
}
Game* FBEngine::getGame() {
	return game;
}

bool FBEngine::isRunning() {
	return running;
}
void FBEngine::setRunning(bool running) {
	this->running = running;
}

void FBEngine::start() {
	if(game == NULL) {
		return;
	}
	running = true;
	
	while(running) {
		int startTime = time(0);
		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			if(event.type == SDL_QUIT) {
				running = false;
				break;
			} else if(event.type == SDL_KEYUP) {
				game->keyEvent(FBE_KEY_RELEASED, event.key.keysym.sym);
			} else if(event.type == SDL_KEYDOWN) {
				game->keyEvent(FBE_KEY_PRESSED, event.key.keysym.sym);
			} else if(event.type == SDL_MOUSEMOTION) {
				int x = event.motion.x;
				int y = event.motion.y;
				game->mouseEvent(FBE_MOUSE_MOVED, x, y, event.button.button);
			} else if(event.type == SDL_MOUSEBUTTONUP) {
				int x = event.motion.x;
				int y = event.motion.y;
				game->mouseEvent(FBE_MOUSE_RELEASED, x, y, event.button.button);
			} else if(event.type == SDL_MOUSEBUTTONDOWN) {
				int x = event.motion.x;
				int y = event.motion.y;
				game->mouseEvent(FBE_MOUSE_PRESSED, x, y, event.button.button);
			}
		}
		game->update();
		game->render();
		glFlush();
		SDL_GL_SwapBuffers();
		int newTime = time(0);
		int timeTaken = newTime-startTime;
		if(timeTaken > game->getRequestedFPS()) {
			SDL_Delay(5);
		} else {
			SDL_Delay((game->getRequestedFPS()) - timeTaken);
		}
		
		game->setReportedFPS((timeTaken/1000));
	}
}
Error:

Code: Select all

CompileC build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/Objects-normal/i386/main.o main.cpp normal i386 c++ com.apple.compilers.gcc.4_0
cd /Users/jacobgarber/Desktop/SDLOpenGLTest
setenv LANG en_US.US-ASCII
/Developer/usr/bin/gcc-4.0 -x c++ -arch i386 -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -isysroot /Developer/SDKs/MacOSX10.5.sdk -mfix-and-continue -fvisibility-inlines-hidden -mmacosx-version-min=10.5 -gdwarf-2 -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/SDLOpenGLTest.hmap -F/Users/jacobgarber/Desktop/SDLOpenGLTest/build/Debug -F/Users/jacobgarber/Library/Frameworks -F/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/Debug/include -I/Users/jacobgarber/Library/Frameworks/SDL.framework/Headers -I/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks/SDL.framework/Headers -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/DerivedSources/i386 -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/DerivedSources -include /var/folders/RI/RIxlp3ksGAWi66A-rj783E+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/SDLOpenGLTest_Prefix-eenihgompdfifncobrlrsehetnkm/SDLOpenGLTest_Prefix.pch -c /Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp -o /Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/Objects-normal/i386/main.o

/Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp: In function 'int SDL_main(int, char**)':
/Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp:12: error: cannot allocate an object of abstract type 'MyGame'
/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.h:5: note:   because the following virtual functions are pure within 'MyGame':
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:19: note:  virtual void Game::update() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:20: note:  virtual void Game::render() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:21: note:  virtual void Game::init() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:23: note:  virtual void Game::keyEvent(int, int) const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:24: note:  virtual void Game::mouseEvent(int, int, int, int) const

CompileC build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/Objects-normal/ppc/main.o main.cpp normal ppc c++ com.apple.compilers.gcc.4_0
cd /Users/jacobgarber/Desktop/SDLOpenGLTest
setenv LANG en_US.US-ASCII
/Developer/usr/bin/gcc-4.0 -x c++ -arch ppc -fmessage-length=0 -pipe -Wno-trigraphs -fpascal-strings -fasm-blocks -O0 -Wreturn-type -Wunused-variable -isysroot /Developer/SDKs/MacOSX10.5.sdk -mfix-and-continue -mtune=G5 -fvisibility-inlines-hidden -mmacosx-version-min=10.5 -gdwarf-2 -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/SDLOpenGLTest.hmap -F/Users/jacobgarber/Desktop/SDLOpenGLTest/build/Debug -F/Users/jacobgarber/Library/Frameworks -F/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/Debug/include -I/Users/jacobgarber/Library/Frameworks/SDL.framework/Headers -I/Developer/SDKs/MacOSX10.5.sdk/Library/Frameworks/SDL.framework/Headers -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/DerivedSources/ppc -I/Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/DerivedSources -include /var/folders/RI/RIxlp3ksGAWi66A-rj783E+++TI/-Caches-/com.apple.Xcode.501/SharedPrecompiledHeaders/SDLOpenGLTest_Prefix-drfvvyxxhgcgicabnlgfhedlivxo/SDLOpenGLTest_Prefix.pch -c /Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp -o /Users/jacobgarber/Desktop/SDLOpenGLTest/build/SDLOpenGLTest.build/Debug/SDLOpenGLTest.build/Objects-normal/ppc/main.o

/Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp: In function 'int SDL_main(int, char**)':
/Users/jacobgarber/Desktop/SDLOpenGLTest/main.cpp:12: error: cannot allocate an object of abstract type 'MyGame'
/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.h:5: note:   because the following virtual functions are pure within 'MyGame':
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:19: note:  virtual void Game::update() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:20: note:  virtual void Game::render() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:21: note:  virtual void Game::init() const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:23: note:  virtual void Game::keyEvent(int, int) const
/Users/jacobgarber/Desktop/SDLOpenGLTest/Game.h:24: note:  virtual void Game::mouseEvent(int, int, int, int) const
qpHalcy0n
Respected Programmer
Respected Programmer
Posts: 387
Joined: Fri Dec 19, 2008 3:33 pm
Location: Dallas
Contact:

Re: Extending a class with pure virtual functions

Post by qpHalcy0n »

You can not instantiate a pure virtual class object. This is called an abstract class or "interface".

They can not be instantiated.
User avatar
programmerinprogress
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 632
Joined: Wed Oct 29, 2008 7:31 am
Current Project: some crazy stuff, i'll tell soon :-)
Favorite Gaming Platforms: PC
Programming Language of Choice: C++!
Location: The UK
Contact:

Re: Extending a class with pure virtual functions

Post by programmerinprogress »

You can only use pointers to an abstract class, with memory allocated to a derived class e.g.

Base* pBase = new Derived();

This is one method of polymorphism in C++.

just thought I would elaborate further on the previous (you cant't instantiate abstract classes)
---------------------------------------------------------------------------------------
I think I can program pretty well, it's my compiler that needs convincing!
---------------------------------------------------------------------------------------
And now a joke to lighten to mood :D

I wander what programming language anakin skywalker used to program C3-PO's AI back on tatooine? my guess is Jawa :P
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

Re: Extending a class with pure virtual functions

Post by ajtgarber »

I know this, but how do I get MyGame to not be an abstract class?
User avatar
Ginto8
ES Beta Backer
ES Beta Backer
Posts: 1064
Joined: Tue Jan 06, 2009 4:12 pm
Programming Language of Choice: C/C++, Java

Re: Extending a class with pure virtual functions

Post by Ginto8 »

ok the fix was easy:

Code: Select all

#pragma once

#include "Game.h"

class MyGame : public Game {
public:
   MyGame(int width, int height);
   
   virtual void init() const;
   virtual void update() const;
   virtual void render() const;
   
   virtual void keyEvent(int event, int key) const;
   virtual void mouseEvent(int event, int x, int y, int button) const;
};
the error was caused because the implementations you defined were not const, so it thought you still had more things to define.
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
User avatar
programmerinprogress
Chaos Rift Devotee
Chaos Rift Devotee
Posts: 632
Joined: Wed Oct 29, 2008 7:31 am
Current Project: some crazy stuff, i'll tell soon :-)
Favorite Gaming Platforms: PC
Programming Language of Choice: C++!
Location: The UK
Contact:

Re: Extending a class with pure virtual functions

Post by programmerinprogress »

ajtgarber wrote:I know this, but how do I get MyGame to not be an abstract class?
Simple answer without looking at the code, derive a new class and implement all of the methods that you haven't defined (the ones you declared as =0).
---------------------------------------------------------------------------------------
I think I can program pretty well, it's my compiler that needs convincing!
---------------------------------------------------------------------------------------
And now a joke to lighten to mood :D

I wander what programming language anakin skywalker used to program C3-PO's AI back on tatooine? my guess is Jawa :P
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

Re: Extending a class with pure virtual functions

Post by ajtgarber »

Thanks for all the help guys :) , now its giving me another error :P. I'm not really sure why though... sorry I'm not quite used to the C++ compiler messages yet

Code: Select all

/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19:0 /Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19: error: passing 'const MyGame' as 'this' argument of 'int Game::getWidth()' discards qualifiers


/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19:0 /Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19: error: passing 'const MyGame' as 'this' argument of 'int Game::getHeight()' discards qualifiers


/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19:0 /Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19: error: passing 'const MyGame' as 'this' argument of 'int Game::getWidth()' discards qualifiers


/Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19:0 /Users/jacobgarber/Desktop/SDLOpenGLTest/MyGame.cpp:19: error: passing 'const MyGame' as 'this' argument of 'int Game::getHeight()' discards qualifiers
Code its pointing to (MyGame init function):

Code: Select all

void MyGame::init() const {
	SDL_WM_SetCaption("Test SDL/OpenGL", NULL);
	
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0, this->getWidth(), this->getHeight(), 0, -1, 1);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
User avatar
Ginto8
ES Beta Backer
ES Beta Backer
Posts: 1064
Joined: Tue Jan 06, 2009 4:12 pm
Programming Language of Choice: C/C++, Java

Re: Extending a class with pure virtual functions

Post by Ginto8 »

well maybe you should, instead of adding const's to your MyGame class, remove the const's from the Game abstract class. That would probably be the better strategy.
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
ajtgarber
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 97
Joined: Wed Jun 10, 2009 8:56 am

Re: Extending a class with pure virtual functions

Post by ajtgarber »

Thanks :D, what exactly does the const after the function header actually mean? I remember reading somewhere that a function with const after it can't call another function that doesn't have it.

P.S Ginto8 nice signature
User avatar
Ginto8
ES Beta Backer
ES Beta Backer
Posts: 1064
Joined: Tue Jan 06, 2009 4:12 pm
Programming Language of Choice: C/C++, Java

Re: Extending a class with pure virtual functions

Post by Ginto8 »

ajtgarber wrote:Thanks :D, what exactly does the const after the function header actually mean? I remember reading somewhere that a function with const after it can't call another function that doesn't have it.
A function with const after it cannot modify any data of the class. This is so that the compiler can tell if a method can be used safely by a const instance of the class, because if a function tries to modify const data, it won't work exactly the way you want it to. ;)
ajtgarber wrote:P.S Ginto8 nice signature
:mrgreen:
Quit procrastinating and make something awesome.
Ducky wrote:Give a man some wood, he'll be warm for the night. Put him on fire and he'll be warm for the rest of his life.
Post Reply