Virtual Function Problemo

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

Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Virtual Function Problemo

Post by Pornomag »

Well I'm trying to make my game and I've had a little trouble... OK basically, I have these Two Classes called:

BaseImage - Abstract
SWRImage2D - Inherits from BaseImage

BaseImage has a pure virtual function called LoadImage(const char*), and SWRImage2D over-rides that method and loads an Image with SDL. Now the problem is, I made an object of SWRImage2D inside a class, and I've tried to Load an image, but it seems to be that I'm getting a pure-virtual function call from LoadImage().

Now, however if I put the declaration (make a local variable of SWRImage2D) of the Object inside the Init() method, where I am doing my Loading it seems to work fine, why the hell is this happening???

Here's my code:

NCGame.h

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__

#include <SDL.h>
#include "Scene.h"

#include "SWRImage2D.h"

class NCGame : public ge::util::Scene
{
private:
	ge::img::SWRImage2D PlayerNC;
	ge::img::SWRImage2D RainbowTrail;
public:
	NCGame();
	// Main function for the main loop
	virtual int MainLoop();

	// Initializes variables
	virtual int Init();

	// Handles user input
	virtual void HandleInput(SDL_Event&);
};

#endif // __NCGAME_H__

NCGame.cpp

Code: Select all

int NCGame::Init()
{
	// Load The Images
	PlayerNC.setAlphaChannel(true); // Image uses alpha

/*\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
- This is where it is calling a Pure Virtual Function!!!!
//////////////////////////////////////////*/
// But if I did declared it as a local variable it works fine:
/*
ge::img::SWRImage2D PlayerNC; // The Image declared as a local variable
*/
	if(PlayerNC.LoadImage("resources/images/NyanCatSingle.png") == false){
		return -1;
	}

	RainbowTrail.setAlphaChannel(true);
	if(RainbowTrail.LoadImage("resources/images/rainbow1.png") == false){
		return -2;
	}

	return 0;
}
Can someone please explain what the heck is going on?
User avatar
short
ES Beta Backer
ES Beta Backer
Posts: 548
Joined: Thu Apr 30, 2009 2:22 am
Current Project: c++, c
Favorite Gaming Platforms: SNES, PS2, SNES, SNES, PC NES
Programming Language of Choice: c, c++
Location: Oregon, US

Re: Virtual Function Problemo

Post by short »

What? You can't call a pure virtual method, ever. The compiler won't let you. I just woke up, but I'm not sure you have explained what is going wrong thoroughly enough.

edit: (coffee) post the source code for your base class.
My github repository contains the project I am currently working on,
link: https://github.com/bjadamson
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Virtual Function Problemo

Post by Falco Girgis »

I'm going to need to see definitions of both the base class and the implementation class.

Also, you should get rid of the pragma here:

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__
This is redundant. And that pragma isn't guaranteed to work on every compiler.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: Virtual Function Problemo

Post by superLED »

GyroVorbis wrote:I'm going to need to see definitions of both the base class and the implementation class.

Also, you should get rid of the pragma here:

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__
This is redundant. And that pragma isn't guaranteed to work on every compiler.
Isn't #endif required?
Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Re: Virtual Function Problemo

Post by Pornomag »

OK thanks for replying :) here's my source code.

The BaseImage Class:

BaseImage.h

Code: Select all

/************************************************************************
* BaseImage.h
*
* BaseImage is an Abstract class, for Image Classes. It holds the basic properties, 
* loading and destroying an Image. Defines if the Image has Alpha blending or
* a mask colour.
*
* Inside namespace ge::img.
*
* Pure Virtual Members:
*	1. LoadImage(const char* filename);
*	2. Destroy();
*
* Virtual Functions:
*	1. setAlphaValue(Uint8); 
*
* Need to do:
*	1. Overload left/shift operators for console/file output ( << and >> ).
*
*
* Notes:
*	1. ge::img::Image^ inherits from this class, so it is
* possible to do Polymorphisms with this Class.
*
* ^ All versions of the Image Classes.
*
*											Author: Miguel Martin (c) 2011
*************************************************************************/

#pragma once
#ifndef __BASEIMAGE_H__
#define __BASEIMAGE_H__
#include <SDL.h>

namespace ge{

	namespace img{

		class BaseImage
		{
		private:
			// If all rMask, gMask and bMask are set to -1, then there will be no mask colour
			short rMask; // The Red Mask Colour, ranges from 0 - 255, if -1 then there will be no Mask.
			short gMask; // The Blue Mask Colour, ranges from 0 - 255, if -1 then there will be no Mask.
			short bMask; // The Green Mask Colour, ranges from 0 - 255, if -1 then there will be no  Mask.
			Uint8 alphaValue; // The Alpha value, ranges from 0 - 255, if 0 then completely transparent, if 255 then its completely visible.

			bool alpha; // This is completely different from alphaValue, if this is true when loading it will use the alpha channel from the image.
		public:
			BaseImage(void); // Default Constructor, sets Red, Green, Blue colour values to -1. Also sets alpha to false and alphaValue to 255 (completely visible).
			BaseImage(Uint8 alphaValue); // Sets the alpha value...
			BaseImage(bool alpha); // If it's true, then the next image that is loaded will have an alpha channel.
			BaseImage(short maskRed, short maskGreen, short maskBlue); // Sets the red, green and blue mask colour values
			BaseImage(short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values.
			BaseImage(short maskRed, short maskGreen, short maskBlue, bool alpha); // Sets the red, green and blue colour values and if the image has alpha blending or not.
			BaseImage(short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values and if the image has alpha blending or not.
			BaseImage(const BaseImage&); // Copy Constructor.
			~BaseImage(void); // Destructor, does nothing. May do something in a later date.
			
			/////////////////////////////
			/// - Pure Virtual Functions

			// Loads an Image from a file.
			virtual bool LoadImage(const char* filename) = 0;
			// Loads an Image from a file, but first sets all variables, then loads an Image.
			virtual bool LoadImage(const char* filename, short maskRed, short maskGreen, short maskBlue, bool alphaChannel = false, Uint8 alphaVal = 255) = 0;

			// Destroys the allocated Image.
			virtual void Destroy() = 0;

			// Draws the actual image.
			virtual bool Draw() = 0;


			////////////////////////////
			/// - Getters and Setters
			// Mask Colours - Red, Green, Blue and Alpha value, ranges from 0 - 255.
			// If all (Red, Green and Blue) are -1 then there is not Mask colour.

			// Sets the Red Mask Colour value, ranges from 0 - 255.
			// If set to -1 then no mask colour is required (Will be 0 if other mask colours are not -1).
			// But in memory it will be -1.
			void setRedMaskColour(short r);
			// Returns the Red Mask colour, ranges from 0 - 255.
			// If set to -1 then there is no red mask colour.
			short getRedMaskColour() const;

			// Sets the Green Mask Colour value, ranges from 0 - 255.
			// If set to -1 then no mask colour is required (Will be 0 if other mask colours are not -1).
			// But in memory it will be -1.
			void setGreenMaskColour(short g);
			// Returns the Green Mask colour, ranges from 0 - 255.
			// If set to -1 then there is no green mask colour.
			short getGreenMaskColour() const;

			// Sets the Blue Mask Colour value, ranges from 0 - 255.
			// If set to -1 then no mask colour is required (Will be 0 if other mask colours are not -1).
			// But in memory it will be -1.
			void setBlueMaskColour(short b);
			// Returns the Blue Mask colour, ranges from 0 - 255.
			// If set to -1 then there is no blue mask colour.
			short getBlueMaskColour() const;

			// Sets the Alpha Value, ranges from 0 - 255. 
			// 0 is completely transparent, 255 is opaque (completely visible).
			// Is virtual for Software Rendering and OpenGL Rendering...
			virtual void setAlphaValue(Uint8 alphaValue);
			// Returns the Alpha masking value, ranges from 0 - 255. 
			// 0 is completely transparent, 255 is opaque (completely visible).
			short getAlphaValue() const;

			// Sets if the image uses the Alpha Channel.
			// If true, then the image uses the Alpha Channel.
			void setAlphaChannel(bool alphaChannel);
			// Returns true if the Image is using alphaChannel.
			bool isUsingAlphaChannel() const;
		};
		
		// end of namespace img
	}

	// end of namespace ge
}
#endif // __BASEIMAGE_H__
BaseImage.cpp

Code: Select all

/************************************************************************
* BaseImage.cpp
*
* BaseImage is an Abstract class, for Image Classes. It holds the basic properties, 
* loading and destroying an Image. Defines if the Image has Alpha blending or
* a mask colour.
*
* Inside namespace ge::img.
*
* Pure Virtual Members:
*	1. LoadImage(const char* filename);
*	2. Destroy();
*
* Need to do:
*	1. Overload left/shift operators for console/file output ( << and >> ).
*
*
*											Author: Miguel Martin (c) 2011
*************************************************************************/

#include "BaseImage.h"

// Default Constructor
ge::img::BaseImage::BaseImage(void)
	: rMask(-1), gMask(-1), bMask(-1), alphaValue(255), alpha(false)
{
	// Set the Red, Green and Blue mask to -1 and alphaValue to 255, for completely visible.
	// And the alpha bool to false so that it doesn't use the alpha channel, by default.
}

ge::img::BaseImage::BaseImage( Uint8 alphaValue )
	: rMask(-1), gMask(-1), bMask(-1), alpha(false)
{
	// Do the same as the Default constructor, except set the requested alpha value...
	this->setAlphaValue(alphaValue);
}

ge::img::BaseImage::BaseImage( bool alpha )
	: rMask(-1), gMask(-1), bMask(-1), alphaValue(255)
{
	// Do the same as the Default constructor, except set a custom value (true/false) if alpha channel is required...
	this->setAlphaChannel(alpha);
}

ge::img::BaseImage::BaseImage( short r, short g, short b )
	: alpha(false), alphaValue(255)
{
	// Do the same as the Default constructor, except set the mask colours to a custom value..
	this->setRedMaskColour(r);
	this->setGreenMaskColour(g);
	this->setBlueMaskColour(b);
}

ge::img::BaseImage::BaseImage( short r, short g, short b, Uint8 alphaValue )
	: alpha(false)
{
	// Do the same as the Default constructor, except set the mask colours and alpha value to a custom value..
	this->setRedMaskColour(r);
	this->setGreenMaskColour(g);
	this->setBlueMaskColour(b);
	this->setAlphaValue(alphaValue);
}

ge::img::BaseImage::BaseImage( short r, short g, short b, bool alpha )
{
	// Do the same as the Default constructor, except set the mask colours and set if alpha channel is required.
	this->setRedMaskColour(r);
	this->setGreenMaskColour(g);
	this->setBlueMaskColour(b);
	this->setAlphaChannel(alpha);
}

ge::img::BaseImage::BaseImage( short r, short g, short b, bool alpha, Uint8 alphaValue )
{
	// Set all private data to custom values
	this->setRedMaskColour(r);
	this->setGreenMaskColour(g);
	this->setBlueMaskColour(b);
	this->setAlphaValue(alphaValue);
	this->setAlphaChannel(alpha);
}

// Copies all the variables...
ge::img::BaseImage::BaseImage( const BaseImage& Obj )
	: rMask(Obj.getRedMaskColour()), gMask(Obj.getGreenMaskColour()), bMask(Obj.getBlueMaskColour()),
	alphaValue((Uint8)Obj.getAlphaValue()), alpha(Obj.isUsingAlphaChannel())
{
}


ge::img::BaseImage::~BaseImage(void)
{
	// Destructor does nothing, may do something in a later date.
}

//////////////////////////
/// - Getters and Setters

// Sets rMask, -1 to 255 are valid values, if parsed in argument is not those values, a warning is shown to stderr.
void ge::img::BaseImage::setRedMaskColour( short r )
{
	// If the parsed in argument ranges from -1 to 255, set the rMask value
	if(r >= -1 && r <= 255){
		rMask = r;
	}
	// else do not set the rMask value and display a warning to stderr.
	else{
		fprintf(stderr, "[WARNING]: Bad Function call to setRedMaskColour(int), parsed in value was: %i. %s.", r, 
			"\nValues should be from -1 - 255.\nrMask was not set a value\n");
	}
}

// returns the rMask value.
short ge::img::BaseImage::getRedMaskColour() const
{
	return rMask;
}

// Sets gMask, -1 to 255 are valid values, if parsed in argument is not those values, a warning is shown to stderr.
void ge::img::BaseImage::setGreenMaskColour( short g )
{
	// If the parsed in argument ranges from -1 to 255, set the gMask value
	if(g >= -1 && g <= 255){
		gMask = g;
	}
	// else do not set the rMask value and display a warning to stderr.
	else{
		fprintf(stderr, "[WARNING]: Bad Function call to setGreenMaskColour(int), parsed in value was: %i. %s.", g, 
			"\nValues should be from -1 - 255.\ngMask was not set a value\n");
	}
}

// returns the gMask value.
short ge::img::BaseImage::getGreenMaskColour() const
{
	return gMask;
}

// Sets bMask, -1 to 255 are valid values, if parsed in argument is not those values, a warning is shown to stderr.
void ge::img::BaseImage::setBlueMaskColour( short b )
{
	// If the parsed in argument ranges from -1 to 255, set the bMask value
	if(b >= -1 && b <= 255){
		bMask = b;
	}
	// else do not set the rMask value and display a warning to stderr.
	else{
		fprintf(stderr, "[WARNING]: Bad Function call to setBlueMaskColour(int), parsed in value was: %i. %s.", b, 
			"\nValues should be from -1 - 255.\ngMask was not set a value\n");
	}
}

// returns the bMask value.
short ge::img::BaseImage::getBlueMaskColour() const
{
	return bMask;
}

// Sets the alphaValue to aValue, 0 - 255 are valid values, if a parsed in argument are not those values, a warning is shown to stderr.
void ge::img::BaseImage::setAlphaValue( Uint8 aValue )
{
	// If the parsed in argument ranges from 0 to 255, set the alphaValue value
	if(aValue >= 0 && aValue <= 255){
		alphaValue = aValue;
	}
	// else do not set the rMask value and display a warning to stderr.
	else{
		fprintf(stderr, "[WARNING]: Bad Function call to setAlphaValue(Uint8), parsed in value was: %i. %s.", aValue, 
			"\nValues should be from -1 - 255.\ngMask was not set a value\n");
	}
}

// returns the alphaValue.
short ge::img::BaseImage::getAlphaValue() const
{
	return alphaValue;
}

// Sets the bool for alphaChannel. If this is true, the next image that is loaded will use the alpha channel.
void ge::img::BaseImage::setAlphaChannel( bool alphaChannel )
{
	alpha = alphaChannel;
}

// returns alpha, true if the image is using alpha channel, false if it's not.
bool ge::img::BaseImage::isUsingAlphaChannel() const
{
	return alpha;
}
The SWRImage2D:

SWRImage2D.h

Code: Select all

/************************************************************************
* SWRImage2D.h
* 
* Interface of SWRImage2D. SWRImage2D is a class that does Software Rendering
* of a 2-Dimensional image. It inherits from Vector<int> and BaseImage.
*
* The Reason it inherits from Vector<int>, is because it has 2-Dimensional
* coordinates. And it only draws on the actual pixels on the screen.
* 
* Inside namespace ge::img.
*
* Pure Virtual Members:
*	1. LoadImage(const char* filename);
*	2. Destroy();
*
* Need to do:
*	1. Overload left/shift operators for console/file output ( << and >> ).
*	2. Copying images
*	3. Assignment operator
*
*
*											Author: Miguel Martin (c) 2011
*************************************************************************/
#pragma once
#ifndef __SWRIMAGE2D_H__
#define __SWRIMAGE2D_H__

#include "BaseImage.h"
#include "Vertex2D.h"
#include <SDL.h>

namespace ge{

	namespace img{

		class SWRImage2D : public ge::img::BaseImage, public ge::util::Vertex2D<int>
		{
		protected:
			SDL_Surface* image; // The actual Image
		public:
			SWRImage2D(void); // Default Constructor, zero's everything out. Calls all default constructors.

			// Constructors from BaseImage
			SWRImage2D(short maskRed, short maskGreen, short maskBlue); // Sets the red, green and blue mask colour values
			SWRImage2D(short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values.
			SWRImage2D(short maskRed, short maskGreen, short maskBlue, bool alpha); // Sets the red, green and blue colour values and if the image has alpha blending or not.
			SWRImage2D(short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values and if the image has alpha blending or not.

			// Constructors from BaseImage and Vertex2D merged
			SWRImage2D(int x, int y, short maskRed, short maskGreen, short maskBlue); // Sets the red, green and blue mask colour values
			SWRImage2D(int x, int y, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values.
			SWRImage2D(int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha); // Sets the red, green and blue colour values and if the image has alpha blending or not.
			SWRImage2D(int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values and if the image has alpha blending or not.

			// Constructors from BaseImage, but load the image
			SWRImage2D(const char* filename, short maskRed, short maskGreen, short maskBlue); // Sets the red, green and blue mask colour values
			SWRImage2D(const char* filename, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values.
			SWRImage2D(const char* filename, short maskRed, short maskGreen, short maskBlue, bool alpha); // Sets the red, green and blue colour values and if the image has alpha blending or not.
			SWRImage2D(const char* filename, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values and if the image has alpha blending or not.

			// Constructors from BaseImage and Vertex2D merged, but load the image
			SWRImage2D(const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue); // Sets the red, green and blue mask colour values
			SWRImage2D(const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values.
			SWRImage2D(const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha); // Sets the red, green and blue colour values and if the image has alpha blending or not.
			SWRImage2D(const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue); // Sets the red, green, blue and alpha colour values and if the image has alpha blending or not.

			// Constructor from Vertex2D
			SWRImage2D(int x, int y);

			// Copy Constructor - Calls BaseImage and Vertex2D's copy constructor
			SWRImage2D(const SWRImage2D&);

			~SWRImage2D(void); // Destructor which calls Destroy()

			///////////////////////
			/// - Image Functions

			// Loads an Image from a file, stores it in SDL_Surface* image.
			virtual bool LoadImage(const char* filename);
			// Loads an Image from a file, but first sets all variables, then loads an Image and stores it in SDL_Surface* image.
			virtual bool LoadImage(const char* filename, short maskRed, short maskGreen, short maskBlue, bool alphaChannel = false, Uint8 alphaVal = 255);

			// Destroys the allocated Image.
			virtual void Destroy();

			// Draws the actual image.
			virtual bool Draw();

			/////////////////////
			/// - Getter/Setters

			// Sets the Alpha Value, ranges from 0 - 255. 
			// 0 is completely transparent, 255 is opaque (completely visible).
			virtual void setAlphaValue(Uint8 alphaValue);

			// Returns the SDL_Surface* for some functions required for it.
			SDL_Surface* getImageSurface() const;
		};

		// end of namespace img
	}
	
	// end of namespace ge
}

#endif // __SWRIMAGE2D_H__
SWRImage.cpp

Code: Select all

/************************************************************************
* SWRImage2D.cpp
* 
* Implementation of SWRImage2D. SWRImage2D is a class that does Software Rendering
* of a 2-Dimensional image. It inherits from Vector<int> and BaseImage.
*
* The Reason it inherits from Vector<int>, is because it has 2-Dimensional
* coordinates. And it only draws on the actual pixels on the screen.
* 
* Inside namespace ge::img.
*
* Pure Virtual Members:
*	1. LoadImage(const char* filename);
*	2. Destroy();
*
* Need to do:
*	1. Overload left/shift operators for console/file output ( << and >> ).
*	2. Copying images
*	3. Assignment operator
*
* NOTE:
*	All constructors make image point to nothing in the initializer list.
*
*											Author: Miguel Martin (c) 2011
*************************************************************************/

#include "SWRImage2D.h"
 // SDL_image.h is required to use SDL_LoadIMG();
#include <SDL_image.h>

// Default constructor, zero's everything out.
ge::img::SWRImage2D::SWRImage2D(void)
	: Vertex2D<int>(), BaseImage(), image(0)
{
	fprintf(stdout, "[NOTICE]: Inside SWRImage2D\n");
}

// Constructors from BaseImage
ge::img::SWRImage2D::SWRImage2D( short maskRed, short maskGreen, short maskBlue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue), image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alphaValue), image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( short maskRed, short maskGreen, short maskBlue, bool alpha )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alpha), image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alpha, alphaValue), image(0)
{
}

// Constructors from BaseImage and Vertex2D merged
ge::img::SWRImage2D::SWRImage2D( int x, int y, short maskRed, short maskGreen, short maskBlue )
	:   Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue), image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( int x, int y, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskBlue, alphaValue),  image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha )
	:  Vertex2D<int>(x, y), BaseImage(maskRed, maskBlue, alpha), image(0)
{
}

ge::img::SWRImage2D::SWRImage2D( int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue, alpha, alphaValue),  image(0)
{
}


// Constructors from BaseImage, but load the image
ge::img::SWRImage2D::SWRImage2D( const char* filename, short maskRed, short maskGreen, short maskBlue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alphaValue), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, short maskRed, short maskGreen, short maskBlue, bool alpha )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alpha), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue )
	: Vertex2D<int>(), BaseImage(maskRed, maskGreen, maskBlue, alpha, alphaValue), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}


// Constructors from BaseImage and Vertex2D merged, but load the image
ge::img::SWRImage2D::SWRImage2D( const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue),  image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, Uint8 alphaValue )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue, alphaValue), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue, alpha), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

ge::img::SWRImage2D::SWRImage2D( const char* filename, int x, int y, short maskRed, short maskGreen, short maskBlue, bool alpha, Uint8 alphaValue )
	: Vertex2D<int>(x, y), BaseImage(maskRed, maskGreen, maskBlue, alpha, alphaValue), image(0)
{
	// After the variables have been set, load the image
	LoadImage(filename);
}

// Constructor from Vertex2D
ge::img::SWRImage2D::SWRImage2D( int x, int y )
	: Vertex2D<int>(x, y), image(0)
{
}

// Copy Constructor - Calls BaseImage and Vertex2D's copy constructor
ge::img::SWRImage2D::SWRImage2D( const SWRImage2D &Obj )
	: Vertex2D<int>(Obj), BaseImage(Obj), image(0)
{
}

ge::img::SWRImage2D::~SWRImage2D(void)
{
	// if the image does not point to anything, then destroy it.
	if( image != 0 ){
		this->Destroy();
	}
}

bool ge::img::SWRImage2D::LoadImage( const char* filename )
{
	// If the image does not point to NULL (0), destroy it first before loading.
	if( image != 0 ){
		this->Destroy();
	}

	// If the filename has got something in it.
	if( filename != "" ){
		// tempImage is a temp SDL_Surface to convert it to the screen settings and if the client wants alpha blending,
		// or mask colours etc.
		SDL_Surface* tempImage = 0; // Make it point to nothing first.

		tempImage = IMG_Load(filename); // Load the image, using IMG_Load(const char*), this should load a variety of image files.

		//If the image loaded successfully, then we shall optimize it to suit the clients fancy.
		if(tempImage != 0) {

			if(this->isUsingAlphaChannel() == false){
				// Create an optimized image without the Alpha channel
				this->image = SDL_DisplayFormat(tempImage);
			}else{
				// Create an optimized image with the Alpha.
				this->image = SDL_DisplayFormatAlpha(tempImage);
			}

			// Free the temp tempImage, as we no longer need it.
			SDL_FreeSurface(tempImage); 

			// If 
			if(this->getRedMaskColour() != -1 
				|| this->getGreenMaskColour() != -1 
				|| this->getBlueMaskColour() != -1){
					// Create a maskColour, using the Mask colours.
					// And the image's format.
					Uint32 maskColour = SDL_MapRGB(image->format, 
						static_cast<Uint8>(getRedMaskColour()),
						static_cast<Uint8>(getGreenMaskColour()), 
						static_cast<Uint8>(getBlueMaskColour()));

					// Set the Colour key (mask colour) to be the maskColour
					SDL_SetColorKey(image, SDL_SRCCOLORKEY, maskColour); 
			}
		}
		// else if the image is NULL (an error occurred while loading) return false
		else{
			// Display an error message to stderr, and show why it failed to load.
			fprintf(stderr, "[ERROR]: Failed to load file from:\n\"%s\": %s\n",
				filename, IMG_GetError()); 
			return false;
		}
	}
	// If the filename has nothing in it, then display an error message to stderr. 
	else{
		fprintf(stderr, "[ERROR]: LoadImage(const char*) failed, because the filename you passed through the function is nothing.\n");
		return false;
	}

	// If everything went OK while loading the image, return true;
	return true;
}

bool ge::img::SWRImage2D::LoadImage( const char* filename, short maskRed, short maskGreen, short maskBlue, bool alphaChannel /*= false*/, Uint8 alphaVal /*= 255*/ )
{
	// Set the data parsed into the function
	this->setRedMaskColour(maskRed);
	this->setGreenMaskColour(maskGreen);
	this->setBlueMaskColour(maskBlue);
	this->setAlphaChannel(alphaChannel);
	this->setAlphaValue(alphaVal);

	// and then call LoadImage.
	return LoadImage(filename);
}


// Draws the actual image.
bool ge::img::SWRImage2D::Draw()
{
	SDL_Rect position = { this->getXCoordinate(), this->getYCoordinate() };
	
	if(SDL_BlitSurface(image, // The image to draw
		0, // Cropping set to 0, as there is none
		SDL_GetVideoSurface(), // The screen to draw on
		0//&position // The location on the screen
		) == -1)
	{
		// If it failed to Draw on the screen.
		fprintf(stdout, "[ERROR]: ge::swr::Image2D::Draw(); failed: %s.\n", SDL_GetError());
	}

	return true;
}

// Releases the image surface.
void ge::img::SWRImage2D::Destroy()
{
	// Release the image surface. (:, 
	SDL_FreeSurface(image);
	image = 0; // and then set the image to null
}

// Sets the Alpha Value of the image
void ge::img::SWRImage2D::setAlphaValue( Uint8 alphaValue )
{
	// First set the actual value of the alpha value
	BaseImage::setAlphaValue(alphaValue);
	
	// Then change the image's alpha value
	if(SDL_SetAlpha(image, SDL_SRCALPHA, alphaValue) == -1){
		fprintf(stderr, "[ERROR]: SDL_SetAlpha() failed in ge::img::SWRImage2D::setAlphaValue(Uint8)\n[DESCRIPTION]: %s\n", SDL_GetError());
	}
}

SDL_Surface* ge::img::SWRImage2D::getImageSurface() const
{
	return image;
}

And just incase you were wondering what the heck Vertex2D<T> was, well here it is:

Vector.h

Code: Select all

/************************************************************************
* Vertex2D.h
* 
* Interface and implementation for Vector2D class, which contains X and Y coordinates 
* for something, a Two-Dimensional Vertex. It is a template class, so this works 
* with any data type, but try to keep the data types a primitive number.
*
* Inside namespace ge::util.
*
* Use:
*	Use this however you please, if something has 2D coordinates, you should
*	use this as the base class.
*
* Things to do:
*	1. File support
*	2. Overload Left and Right Shift Operators
*
*										Author: Miguel Martin. (c) 2011.
************************************************************************/
#pragma once
#ifndef __VERTEX2D_H__
#define __VERTEX2D_H__

#include <iostream>

namespace ge{

	namespace util{

		template<typename T>
		class Vertex2D
		{
		private:
			T x; // The X coordinate
			T y; // The Y coordinate
		public:
			// Zero's everything out
			Vertex2D<T>(void)
				: x(0), y(0)
			{
			}
			// Sets the x and y coordinates to custom values.
			Vertex2D<T>(T X, T Y)
				: x(X), y(Y)
			{
			}
			// Copy constructor, copies the parsed in Vertex2D x and y values.
			Vertex2D<T>(const Vertex2D<T> &CoordObj)
				: x(CoordObj.getXCoordinate()), y(CoordObj.getYCoordinate())
			{
			}	

			///////////////////////
			/// - Getters/Setters

			//	Sets the x coordinate to the parsed in argument.
			void setXCoordinate(T x)
			{
				this->x = x;
			}
			// Returns the x coordinate.
			T getXCoordinate() const
			{
				return x;
			}

			// Sets the Y Coordinate to	the parsed in argument.
			void setYCoordinate(T y)
			{
				this->y = y;
			}
			// Returns the Y Coordinate.
			T getYCoordinate() const
			{
				return y;
			}

			///////////////////////////
			/// - Operator Overloading
			// Assignment Operators

			// Copies the X and Y coordinates from the parsed in object to 
			// the Object that called the method.
			const Vertex2D<T>& operator=(const Vertex2D<T> &Obj)
			{
				setXCoordinate(Obj.getXCoordinate()); // Set the X coordinate to the parsed in Vector2 Object's X Coordinate
				setYCoordinate(Obj.getYCoordinate()); // Set the Y coordinate to the parsed in Vector2 Object's Y Coordinate

				return *this;
			}

			//  Sets x to the first element in the array parsed in, and y to the 2nd element parsed in.
			const Vertex2D<T>& operator=(const T VertexArray[2])
			{
				this->setXCoordinate(VertexArray[0]);  // Set the X coordinate to the first element in the array.
				this->setYCoordinate(VertexArray[1]); // Set the Y coordinate to the 2nd element in the array.

				return *this;
			}

			/// Logical Operators
			//////////////////////
			/// - Equality

			// Returns true if the parsed	in object is equal.
			bool operator==(const Vertex2D<T> &Obj)
			{
				// if X and Y are from both objects are equal, it will return true.
				return ((getXCoordinate() == Obj.getXCoordinate()) && (getYCoordinate() == Obj.getYCoordinate()));
			}

			// Returns true if element 0 and element 1 is equal to x and y.
			bool operator==(const T VertexArray[2])
			{
				// if X and Y are equal to element 0 and element 1 in the array, it will return true;
				return ((this->getXCoordinate() == VertexArray[0]) && (this->getYCoordinate() == VertexArray[1]));
			}

			////////////////////
			/// - Non equality

			//Returns true if the parsed in object is not equal.
			bool operator!=(const Vertex2D<T> & Obj)
			{ 
				return !operator==(Obj); 
			}

			// Returns true if element 0 and element 1 is not equal to x and y.
			bool operator!=(const T VertexArray[2]) 
			{ 
				return !operator==(VertexArray); 
			}
		};

		// End of namespace util
	}
	// End of namespace ge
}
#endif // __VERTEX2D_H__
Thank you for your help, I really appreciate it :)
Last edited by Pornomag on Sun Sep 18, 2011 10:17 pm, edited 1 time in total.
Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Re: Virtual Function Problemo

Post by Pornomag »

short wrote:What? You can't call a pure virtual method, ever. The compiler won't let you. I just woke up, but I'm not sure you have explained what is going wrong thoroughly enough.

edit: (coffee) post the source code for your base class.
I over-rid a pure virtual function that I inherited from a Base class right? Now it doesn't seem to call the over-ridden version of that function, I even saw that the vtable is using the methods from the Base Class for the virtual functions. It works fine as a local variable, but if it is a member of a class it fails for example:

This is fine:

Code: Select all

void func(){
    ge::img::SWRImage2D img;
    img.LoadImage("Example.bmp"); // This works perfectly fine
}
However this fails:

Code: Select all

class Example{
   ge::img::SWRimage img;
public:
   void Init(){
       img.LoadImage("Example.bmp"); // This calls the BaseImage's version of LoadImage, which is pure virtual
   }
};
User avatar
szdarkhack
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Fri May 08, 2009 2:31 am

Re: Virtual Function Problemo

Post by szdarkhack »

The only think that could cause something like this would be an incomplete initialization on your object (meaning that the vptr will still be pointing to the base class's vtable and not the derived one's). I cannot imagine why that would happen, though, since even if you don't include it in your initialization list, the default constructor will still be called. At least make sure that the derived class's constructor is called before you attempt to use your function, otherwise i have no clue as to why this happens...
Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Re: Virtual Function Problemo

Post by Pornomag »

UGHHHHHHHH >.< I am getting really frustrated with this... D: I have no idea what I did wrongggggggggggggggg. Thanks for your reply though.
Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Re: Virtual Function Problemo

Post by Pornomag »

Might have to start redesigning my classes then.
Pornomag
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 41
Joined: Tue Jun 21, 2011 5:39 am
Programming Language of Choice: C++

Re: Virtual Function Problemo

Post by Pornomag »

OMG I AM A FREAKEN IDIOT!!!!!!! The reason it is not working is because I defined a DESTRUCTOR in the BaseImage class, now for some reason, which I do not know was making that use the BaseImage's virtual functions. If anyone knows why this is, could you please explain?
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: Virtual Function Problemo

Post by Ginto8 »

If your issue is with a base type destructor, you're probably trying to delete a BaseImage* that actually stores a SWRImage2D. Now I couldn't find that situation in any of the posted code, but if that's the issue, just declare ~BaseImage() as virtual ie:

Code: Select all

virtual ~BaseImage() {}
This causes the compiler to call the destructor of SWRImage2D even when it's being stored as a BaseImage.
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
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Virtual Function Problemo

Post by Falco Girgis »

superLED wrote:
GyroVorbis wrote:I'm going to need to see definitions of both the base class and the implementation class.

Also, you should get rid of the pragma here:

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__
This is redundant. And that pragma isn't guaranteed to work on every compiler.
Isn't #endif required?
....yes... I didn't say to get rid of the #ifdef #define #endif pattern. I said that you should get rid of the pragma.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: Virtual Function Problemo

Post by superLED »

GyroVorbis wrote:
superLED wrote:
GyroVorbis wrote:I'm going to need to see definitions of both the base class and the implementation class.

Also, you should get rid of the pragma here:

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__
This is redundant. And that pragma isn't guaranteed to work on every compiler.
Isn't #endif required?
....yes... I didn't say to get rid of the #ifdef #define #endif pattern. I said that you should get rid of the pragma.
I just asked if #endif was required or not. But oh well.
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Virtual Function Problemo

Post by Falco Girgis »

superLED wrote:
GyroVorbis wrote:
superLED wrote:
GyroVorbis wrote:I'm going to need to see definitions of both the base class and the implementation class.

Also, you should get rid of the pragma here:

Code: Select all

#pragma once
#ifndef __NCGAME_H__
#define __NCGAME_H__
This is redundant. And that pragma isn't guaranteed to work on every compiler.
Isn't #endif required?
....yes... I didn't say to get rid of the #ifdef #define #endif pattern. I said that you should get rid of the pragma.
I just asked if #endif was required or not. But oh well.
OH, my bad! Yeah, you have to end the #ifdef still. Didn't mean to get up your ass. :oops:
User avatar
szdarkhack
Chaos Rift Cool Newbie
Chaos Rift Cool Newbie
Posts: 61
Joined: Fri May 08, 2009 2:31 am

Re: Virtual Function Problemo

Post by szdarkhack »

Ginto8 wrote:If your issue is with a base type destructor, you're probably trying to delete a BaseImage* that actually stores a SWRImage2D. Now I couldn't find that situation in any of the posted code, but if that's the issue, just declare ~BaseImage() as virtual ie:

Code: Select all

virtual ~BaseImage() {}
This causes the compiler to call the destructor of SWRImage2D even when it's being stored as a BaseImage.
Damn, how did i miss that... Anyway, yes, anytime you use virtual functions it's a rule of thumb to make your base destructor virtual as well, otherwise you get some serious problems (depending on the occasion you can even slice your object in half and leak the base part). So make sure to always use virtual destructors when you want polymorphism :)
Post Reply