C++ Header File Needs a Reference to a Function of Another Class - c++

I have incorporated polymorphism with a single subclass for now. Two of these functions, as seen in the following code, Draw() and SetValue(int,int,int) are causing linker errors.
#include "Header.h"
class Object{
int tag;
public:
void SetValues(int,int,int);
void Draw();
int getTag(){
return tag;
}
};
class Square: public Object{
int red;
int green;
int blue;
void Draw();
void SetValues(int red2,int green2, int blue2){
red=red2;
green=green2;
blue=blue2;
}
};
void Square::Draw(){
// Draws a square with a gradient color at coordinates 0, 10
glBegin(GL_QUADS);
{
glColor3f(red, green, blue);
glVertex2i(1, 11);
glColor3f(red * .8, green * .8, blue * .8);
glVertex2i(-1, 11);
glColor3f(red * .5, green * .5, blue * .5);
glVertex2i(-1, 9);
glColor3f(red * .8, green * .8, blue * .8);
glVertex2i(1, 9);
}
glEnd();
}
The errors
Error 1 error LNK2019: unresolved external symbol "public: void __cdecl Object::SetValues(int,int,int)" (?SetValues#Object##QEAAXHHH#Z) referenced in function "public: void __cdecl State::DrawAll(void)" (?DrawAll#State##QEAAXXZ) C:\Users\Asher\documents\visual studio 2012\Projects\Procedural Terrain\Procedural Terrain\State.obj Procedural Terrain
Error 2 error LNK2019: unresolved external symbol "public: void __cdecl Object::Draw(void)" (?Draw#Object##QEAAXXZ) referenced in function "public: void __cdecl State::DrawAll(void)" (?DrawAll#State##QEAAXXZ) C:\Users\Asher\documents\visual studio 2012\Projects\Procedural Terrain\Procedural Terrain\State.obj Procedural Terrain
In a larger class, which does no inherit Object's functions, uses DrawAll() with a Draw() call in it.
The cpp file and the two respective header files are as follows.
#include "Header.h"
#include "Object.h"
float rotate_z=0;
class State{
private:
std::vector<Object> storage;
public:
State();
State Interpolate(State, State, double);
void Integrate(State,double, const double);
void DrawAll();
void AddObject(Object);
void RemoveObject(int);
};
State::State(){
}
State State::Interpolate(State current,State previous,const double alpha){
//current*alpha + previous * ( 1.0 - alpha );
return current;
}
void State::Integrate(State current, double t, const double dt){
}
void State::AddObject(Object object){
storage.push_back(object);
}
void State::RemoveObject(int tag){
//for(int i=0;i<storage.size;i++){
// if(storage.at(i).getTag==tag){
//storage.erase(storage.begin()+i);
// }
//}
}
void State::DrawAll(void)
{
// reset view matrix
glLoadIdentity();
// move view back a bit
glTranslatef(0, 0, -30);
// apply the current rotation
glRotatef(rotate_z, 0, 0, 1);
rotate_z += 5;
// by repeatedly rotating the view matrix during drawing, the
// squares end up in a circle
int i = 0, squares = 15;
float red = 0, blue = 1;
for (; i < squares; ++i){
Square square;
Object * squareP=&square;
glRotatef(360.0/squares, 0, 0, 1);
// colors change for each square
red += 1.0/12;
blue -= 1.0/12;
squareP->SetValues(red,0.6,blue);
squareP->Draw();
}
}
The Object header -
#ifndef Object_H
#define Object_H
class Object{
int tag;
public:
void SetValues(int,int,int);
void Draw();
int getTag();
};
class Square: public Object{
int red;
int green;
int blue;
void Draw();
void SetValues(int red2,int green2, int blue2);
};
#endif
Lastly the State header -
#ifndef State_H
#define State_H
#include "Object.h"
#include <vector>
class State{
private:
std::vector<Object> storage;
public:
State();
State Interpolate(State, State, double);
void Integrate(State,double, const double);
void DrawAll();
void AddObject(Object);
void RemoveObject(int);
};
#endif
This is the first C++ project I have worked on and have not fully transferred from a Java background. What could the problem be?

Your Object class has no implementation of SetValues function. You may want a pure virtual function. Same for Draw.
class Object {
virtual void SetValues(int,int,int) = 0;
}
Also note that in C++ functions are not virtual by default. You have to use the virtual keyword explicitly in the base class.
Also class Object seems to be defined at multiple places. Why? Defining it in Object.h would be sufficient.
Also please indent your code because it is very hard to read.
Also std::vector<Object> will not do what you want! Unline Java, where everything is a reference, in C++ things are stored by value in an std::vector and therefore your code is subject to the slicing problem. You want to use at lease a pointer there (std::vector<Object*>) but a smart pointer would be even better (std::vector<std::shared_ptr<Object>>)

Nothing is marked as virtual, and I can't see any implementation for Object::Draw() or Object::SetValues().
In C++ to allow a subclass to override a function in the base class, it needs to be marked as virtual (in Java everything is always "virtual").
You can have "abstract" methods (like Java) by saying
class Object {
public:
virtual void SetValues(int,int,int) = 0;

Related

Equal operator attempting to reference a deleted function, array

I am using SFML to create a space invaders clone with C++. I am quite new to C++ and I'm learning it as I'm working on this project.
I am getting the following error when trying to create a new enemy using the constructor and array to set settings for each created enemy:
1>enemy.cpp
1>C:\Users\dzamm\source\repos\SFML\enemy.cpp(35,1): error C2280: 'Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
1>C:\Users\dzamm\source\repos\SFML\enemy.h(55): message : compiler has generated 'Enemy::operator =' here
1>C:\Users\dzamm\source\repos\SFML\enemy.h(55,1): message : 'Enemy &Enemy::operator =(const Enemy &)': function was implicitly deleted because a data member invokes a deleted or inaccessible function 'sf::RenderWindow &sf::RenderWindow::operator =(const sf::RenderWindow &)'
Enemy Constructor:
Enemy alienArray[NUMBER_OF_ALIENS];
//constructor sets ID number, loads sprite
Enemy::Enemy(const int id, float sp)
{
//set alive
mIsAlive = true;
//set speed
enemySpeed = sp;
// Load an enemy texture
if (!mEnemyTexture.loadFromFile("Media/Textures/PixelSpaceships/red_01.png")) {
// Handle loading error
std::cout << "Oh No! File not loaded." << std::endl;
}
//scale sprite and set texture so we know size
enemySprite.setTexture(mEnemyTexture);
}
Enemy loader method
void Enemy::loader(int noOfAliens) { // might add xPosition;yPosition
for (int i = 0; i < noOfAliens; i++)
{
Enemy alien(i, 10.f); // speed issue
alien.setLocation(i * 100.f + 50.f, alien.getSprite().getGlobalBounds().height / 2);
line 35 alienArray[i] = alien;
//alienArray.push_back(alien);
}
}
1>C:\Users\dzamm\source\repos\SFML\enemy.cpp(35,1): error C2280: 'Enemy &Enemy::operator =(const Enemy &)': attempting to reference a deleted function
Enemy Header file:
#include <SFML/System.hpp>
#include <SFML/Window.hpp>
#include <SFML/Graphics.hpp>
#include <SFML/Network.hpp>
#pragma once
#define NUMBER_OF_ALIENS 4
//class Game;
class Enemy
{
public:
//constructor sets ID number, loads sprite
Enemy() {};
Enemy(const int, float);
sf::Sprite& getSprite();
void kill();
bool isAlive();
void load();
void loader(const int noOfAliens);
void setLocation(float xPosition, float yPosition);
void enemyInstantiator(int noOfEnemies, float xPosition, float yPosition);
void update();
void render(sf::RenderWindow& window);
private:
void enemyBehaviour(std::vector<sf::Sprite>& enemyList);
void enemyMovement(std::vector<Enemy>& enemyList);
private:
sf::Texture mEnemyTexture;
sf::Sprite enemySprite;
//std::vector<Enemy> alienArray;
//std::vector<sf::Sprite> mEnemies;
sf::RectangleShape mEnemyBounds;
sf::RenderWindow mWindow;
bool mIsShooting;
bool mIsAlive;
float enemySpeed;
};
I read on forums that issue is related to working with a copy of the object instead of the original object, however I am not sure how to handle this to reference the original object I'm modifying.
To reproduce create a constructor for Enemy.cpp class, create an entity Enemy alien using for loop in method as shown in Enemy::loader and store the created entity in the Enemy alienArray as shown by index.
The issue was related to an sf::RenderWindow reference that was not being even utilised in the code.
sf::RenderWindow &sf::RenderWindow::operator =(const sf::RenderWindow &)
Once I removed this all errors disappeared.

OOP GUI, Template C++

I'm a game designer coming from a Basic-like programming language and moving to C++.
For a new game I'd like to have a gui programmed using OOP.
My gui currently consists of a gui-class (the outer wrapper), a g_element-class (the middle wrapper containing all the common attributes) and a button-class (overriding and extending the g_element-class).
The problem is I'm getting the following error:
Severity Code Description Project File Line Suppression State
Error LNK2001 unresolved external symbol "public: static class
std::list,class std::allocator > > gui
::el_stack"(?el_stack#?$gui#V?$g_element#Vbutton######2V?$list#V?$g_element#Vbutton####V?$allocator#V?$g_element#Vbutton#####std###std##A)
I really think that this error is not the only problem - I might have a completely wrong approach for this whole thing. I'm also not really sure about that template-thing - I thought I'd be able to expand my g_element-class with gui-elements later (i.e. buttons, sliders, windows...) - but give me a hint if there's something that I can optimise.
Here is my gui.cpp file (so far):
using namespace std;
template <class GUI_ELEMENT> class gui {
protected:
void add_to_stack(GUI_ELEMENT elem) {
// The error comes from here..
// I wanted a list of all my g_elements (buttons)
el_stack.push_back(elem);
printf("size now: %d", el_stack.size());
}
unsigned int get_stack_size() {
return el_stack.size();
}
public:
static list<GUI_ELEMENT> el_stack; // The elements list
void render() {
// here, I'd like to iterate over all i.e. buttons to draw them
}
};
template <class GUI_ELEMENT> class g_element : public gui<g_element<GUI_ELEMENT> >{
private:
float x;
float y;
float w;
float h;
public:
void set_width(float width) {
this->w = width;
}
float get_width() {
return this->w;
}
};
class button : public g_element<button> {
protected:
char* caption;
public:
button(float x, float y, float w, float h, char* caption) {
this->set_width(w);
this->set_caption(caption);
this->add_to_stack(*this);
}
void set_caption(char* caption) {
this->caption = caption;
}
char* get_caption() {
return this->caption;
}
};
I'd like to use my gui like so:
// Create a few test buttons
button b1(50, 50, 100, 50, "Test");
b1.set_width(150);
float s = b1.get_width();
printf("size w: %f", s);
printf("\ncaption: %s", b1.get_caption());
button b2(50, 50, 100, 50, "Test");
button b3(50, 50, 100, 50, "Test2");
button b4(50, 50, 100, 50, "Test3");
// Rendering currently (all buttons at once)
gui<button> G;
G.render();
// but this would be nicer:
gui::render_buttons()
// or
gui<button>::render()
Is there somebody who might help me? Really big thanks in advance!
All static fields should be defined outside of the class definition. In your case you have to add these lines of code after a class definition:
template<class GUI_ELEMENT>
list<GUI_ELEMENT> gui<GUI_ELEMENT>::el_stack;

C++ Multiple Static Functions With Same Name But Different Arguments [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
It appears as though I stumbled across something odd while trying to write my own wrapper for the freeglut api. Basically, I am writing my own little library to make using freeglut easier. One of the first things that I am doing is attempting to implement my own Color class which will be fed into "glClearColor". I am also having it so that you can enter the colors in manually; this means that I will have multiple static methods with the same name but different parameters/arguments. I tried to compile this afterwards but received an error that makes me think that the compiler cant decide which method to use—which is odd considering the two methods in question are still different. One takes a Color3 class and the other a Color4.
Here is some source:
GL.H
#pragma once
#include "Vector3.h"
#include "Color3.h"
#include "Color4.h"
#include <string>
class GL
{
public:
static void initializeGL(int argc, char* argv);
static void initializeDisplayMode(unsigned int displayMode);
static void initializeWindowSize(int width, int height);
static void createWindow(std::string title);
static void mainLoop();
static void translate(const Vector3 &location);
static void translate(float x, float y, float z);
static void rotate(double rotation, float x, float y, float z);
static void rotate(double rotation, const Vector3& axis);
static void color3(const Color3 &color);
static void color4(const Color4 &color);
static void begin();
static void end();
static void pushMatrix();
static void popMatrix();
static void enable(int enableCap);
static void viewport();
static void polygonMode();
static void matrixMode();
static void clearColor(const Color3 &color);
static void clearColor(float red, float green, float blue);
static void clearColor(float red, float green, float blue, float alpha);
static void clearColor(const Color4 &color);
static void vertex3(const Vector3 &location);
static void vertex3(float x, float y, float z);
static void loadIdentity();
static void perspective();
static void depthFunction();
};
GL.cpp
#include "GL.h"
#include "freeglut.h"
void GL::clearColor(const Color3 &color)
{
glClearColor(color.getRed,color.getGreen,color.getBlue, 1.0f);
}
void GL::clearColor(float red, float green, float blue)
{
glClearColor(red, green, blue, 1.0f);
}
void GL::clearColor(float red, float green, float blue, float alpha)
{
}
void GL::clearColor(const Color4 &color)
{
}
And here is my compiler error:
1>------ Build started: Project: GameEngineToolkit, Configuration: Debug Win32 ------
1> Main.cpp
1>c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\main.cpp(47): error C2665: 'GL::clearColor' : none of the 4 overloads could convert all the argument types
1> c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\gl.h(610): could be 'void GL::clearColor(const Color4 &)'
1> c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\gl.h(607): or 'void GL::clearColor(const Color3 &)'
1> while trying to match the argument list '(Color3 *)'
1> GL.cpp
1>c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\gl.cpp(8): error C3867: 'Color3::getRed': function call missing argument list; use '&Color3::getRed' to create a pointer to member
1>c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\gl.cpp(8): error C3867: 'Color3::getGreen': function call missing argument list; use '&Color3::getGreen' to create a pointer to member
1>c:\the capsule\c++\get\gameenginetoolkit\gameenginetoolkit\gl.cpp(8): error C3867: 'Color3::getBlue': function call missing argument list; use '&Color3::getBlue' to create a pointer to member
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
As you can see, it seems that the compiler cant decide between using the Color3 function or the color4 function; I don't understand why because it should be obvious which one to choose(the Color3 one is the one I am using in my main).
As per request, here is my Color3 class:
Color3.h
#pragma once
class Color3
{
public:
Color3();
Color3(float red, float green, float blue);
void setRed(float red);
void setGreen(float green);
void setBlue(float blue);
float getRed();
float getGreen();
float getBlue();
Color3 getColor();
~Color3();
private:
float red;
float green;
float blue;
};
Color3.cpp
#include "Color3.h"
Color3::Color3()
{
}
Color3::Color3(float red, float green, float blue)
{
setRed(red);
setGreen(green);
setBlue(blue);
}
Color3::~Color3()
{
}
float Color3::getRed()
{
return red;
}
float Color3::getGreen()
{
return green;
}
float Color3::getBlue()
{
return blue;
}
void Color3::setBlue(float blue)
{
this->blue = blue;
}
void Color3::setGreen(float green)
{
this->green = green;
}
void Color3::setRed(float red)
{
this->red = red;
}
Color3 Color3::getColor()
{
return *this;
}
The Solution:
Use pointers.
GL.cpp
#include "GL.h"
#include "freeglut.h"
void GL::clearColor(Color3* color)
{
glClearColor(color->getRed(),color->getGreen(),color->getBlue(), 1.0f);
}
void GL::clearColor(float red, float green, float blue)
{
glClearColor(red, green, blue, 1.0f);
}
void GL::clearColor(float red, float green, float blue, float alpha)
{
}
void GL::clearColor(Color4* color)
{
}
GL.H
#pragma once
#include "Vector3.h"
#include "Color3.h"
#include "Color4.h"
#include <string>
class GL
{
public:
static void initializeGL(int argc, char* argv);
static void initializeDisplayMode(unsigned int displayMode);
static void initializeWindowSize(int width, int height);
static void createWindow(std::string title);
static void mainLoop();
static void translate(const Vector3 &location);
static void translate(float x, float y, float z);
static void rotate(double rotation, float x, float y, float z);
static void rotate(double rotation, const Vector3& axis);
static void color3(const Color3 &color);
static void color4(const Color4 &color);
static void begin();
static void end();
static void pushMatrix();
static void popMatrix();
static void enable(int enableCap);
static void viewport();
static void polygonMode();
static void matrixMode();
static void clearColor(Color3* color); // Use pointers instead
static void clearColor(float red, float green, float blue);
static void clearColor(float red, float green, float blue, float alpha);
static void clearColor(Color4* color); // Same thing; no error. =P
static void vertex3(const Vector3 &location);
static void vertex3(float x, float y, float z);
static void loadIdentity();
static void perspective();
static void depthFunction();
};
Well first of all, you're passing a Color3 pointer into an overloaded function that takes two different references.
You have a range of options:
Don't pass a pointer (you have Color3 color in main(), don't pass &color, pass color)
De-reference the pointer to pass a reference (having a Color3* color in main(), pass *color not color)
Change the method or add one to accept a Color3 pointer. This is dumb and I don't advise it. But you can!
Also I know it's not a part of the question but it appears getRed, getGreen, and getBlue are methods that you should append () to.

"class template has already been declared as a non-class template"

Hey i'm getting this odd error when I leave the namespace sf{ declaration in the later code:
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(70): error C2989: 'sf::Body' : class template has already been declared as a non-class template
1>c:\libraries and headers\sfml\sfml-1.6-sdk-windows-vc2008\sfml-1.6\include\sfml\graphics\body.h(11): error C3856: 'sf': class is not a class template
The code worked fine when it wasn't a template class for the past 3 weeks, With the same sf::Body class name; i just recently changed it to make it more flexible. Can i not declare a template class inside a namespace or what?
Here's the code:
#include <SFML/Graphics.hpp>
#include <vector>
#include <math.h>
#include <cmath>
namespace sf{ //when i take this out and the closing bracket the code runs fine
template<typename drawable>
class Body : public sf::Drawable{
private:
sf::Vector2f MoveVal;
std::vector<drawable> Drawables;
public:
Body(const Vector2f& Position = Vector2f(0, 0), const Vector2f& Scale = Vector2f(1, 1), float Rotation = 0.f, const Color& Col = Color(255, 255, 255, 255)){
SetPosition(Position);
SetScale(Scale);
SetRotation(Rotation);
SetColor(Col);};
// Overide Drawable Functions To Detect any Movement
void SetX(float X){
MoveVal.x += X - GetPosition().x;
Drawable::SetX(X);};
void SetY(float Y){
MoveVal.y += Y - GetPosition().y;
Drawable::SetY(Y);};
// Regular Functions
void AddObject(drawable& Object){
Object.Move(GetX(),GetY());
Drawables.push_back(Object);};
void DestroyObject(unsigned short Index){
Drawables.erase(Drawables.begin()+Index);};
void Clear(){
Drawables.clear();};
drawable& GetObject(unsigned short index)
{return Drawables[index];};
unsigned int GetNumbObjects()
{return Drawables.size();};
void Draw(sf::RenderTarget& target){
for(unsigned short I=0; I<Drawables.size(); I++){
//Body offset
Drawables[I].SetPosition(
Drawables[I].GetPosition().x + MoveVal.x,
Drawables[I].GetPosition().y + MoveVal.y);
} // TODO: add tint based on overall Body Color
target.Draw(*this);
//Reset all the Change Values
MoveVal.x=0;
MoveVal.y=0;
};
void Render(sf::RenderTarget& target) const{
for(int I=0; I< Drawables.size(); I++)
Drawables[I].Draw(target);
};
};// Body Class
} //namespace sf
Ok found the problem:
In a previously included header file: Shape.hpp I declare Body as a friend with the following syntax:
friend class Body;
Which apparently makes the compiler assume Body is not a template (no template indication is made)
The correct syntax was:
template <typename drawable>
friend class Body;
Because now the compiler understands Body as a template class
The two most likely candidates based on your information are that Graphics.hpp has mismatched { } or that you had a forward declaration of class Body without marking it a template.
sf::Body is a name that seems to be already taken (for a class whereas you're declaring a template). Are you sure you want to put your code in the sf namespace? It's more customary to use one's own namespaces rather than those of the libraries they use.

Problems with setting up Function Pointers in Templated Class

I am trying to create a generic menu button class that is templated to a class, so I can make this button in any class. I want to create a void function pointer to different functions in that class, so when you click on the New Game button, it will call the NewGame() function etc.
I'm still a little new to the idea of creating function pointers and would like some advice.
I get a crazy link error everytime I try to compile my code now with this Menubutton.
here is the error:
Error 1 error LNK2019: unresolved
external symbol "public: void
__thiscall MENUBUTTON::Draw(void)"
(?Draw#?$MENUBUTTON#VTitleScreen####QAEXXZ)
referenced in function "public:
virtual void __thiscall
TitleScreen::Draw(void)"
(?Draw#TitleScreen##UAEXXZ) TitleScreen.obj
MenuButton.h
template <class t>
struct MENUBUTTON
{
SPRITE Normal; // Sprite to display when not hovered over or pressed down
SPRITE Hover; // Sprite to display when hovered over
RECTANGLE HoverBounds; // The Rectangle that activates the hover flag
t* pClass; // Pointer to the templated class
void (t::*ClickFunction)(); // Pointer to void function
void SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)());
bool IsMouseHover();
void CheckPressed();
void Draw();
};
MenuButton.cpp
#include "Global.h"
template <class t>
void MENUBUTTON<t>::SetButton(int xPos, int yPos, int width, int height, int hPadLeft, int hPadTop, int hWidth, int hHeight, LPCTSTR normalFilePath, LPCTSTR hoverFilePath, t* objectClass, void (t::*ClickFunction)())
{
// Position
Hover.position.x = Normal.position.x = xPos;
Hover.position.y = Normal.position.y = yPos;
Hover.position.z = Normal.position.z = 0;
// Width / Height
Hover.width = Normal.width = width;
Hover.height = Normal.height = height;
// Hover RECTANGLE
HoverBounds.x = xPos + hPadLeft;
HoverBounds.y = yPos + hPadTop;
HoverBounds.width = hWidth;
HoverBounds.height = hHeight;
// Load the Sprites
LoadSprite(&Normal, normalFilePath, width, height, 1, 1);
LoadSprite(&Hover, hoverFilePath, width, height, 1, 1);
// Set the Click function pointer
this->pClass = objectClass;
this->ClickFunction = ClickFunction;
}
template <class t>
void MENUBUTTON<t>::Draw()
{
if(IsMouseHover())
{
DrawSprite(&Hover, 0, Hover.position.x, Hover.position.y, Hover.position.z);
}
else
{
DrawSprite(&Normal, 0, Normal.position.x, Normal.position.y, Normal.position.z);
}
}
template <class t>
bool MENUBUTTON<t>::IsMouseHover()
{
return (((InputData.MousePosition.x >= HoverBounds.x) && (InputData.MousePosition.x <= (HoverBounds.x + HoverBounds.width))) &&
((InputData.MousePosition.y >= HoverBounds.y) && (InputData.MousePosition.y <= (HoverBounds.y + HoverBounds.height)))) ? true : false;
}
Here is my Title Screen which is using the menu button.
TitleScreen.h
class TitleScreen : public BaseState
{
// SPRITES
SPRITE titleScreenBG;
// MENU BUTTONS
MENUBUTTON<TitleScreen> playButton;
MENUBUTTON<TitleScreen> quitButton;
public:
TitleScreen();
virtual void Initialize();
virtual void End();
virtual void Update(float dt, INPUTDATA* input);
virtual void Draw();
void QuitGame();
void NewGame();
};
TitleScreen.cpp
#include "Global.h"
// Constructors
TitleScreen::TitleScreen()
{
}
// Virtual Voids
void TitleScreen::End()
{
}
void TitleScreen::Initialize()
{
this->Enabled = true;
this->Visible = true;
// Initialize sprites
ZeroMemory(&titleScreenBG, sizeof(SPRITE));
LoadSprite(&titleScreenBG, TEXT("../../PNG/TitleScreenBG.png"), 1440, 900, 1, 1);
titleScreenBG.position.x = titleScreenBG.position.y = titleScreenBG.position.z = 0;
// Initialize buttons
ZeroMemory(&playButton, sizeof(MENUBUTTON<TitleScreen>));
playButton.SetButton(55, 170, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
400, 70, // Hover width, Hover height
TEXT("../../PNG/NewGame.png"), TEXT("../../PNG/NewGameH.png"),
this, &TitleScreen::NewGame);
ZeroMemory(&quitButton, sizeof(MENUBUTTON<TitleScreen>));
quitButton.SetButton(55, 240, // x , y
512, 128, // width, height
10, 10, // Left, Top Padding
190, 70, // Hover width, Hover height
TEXT("../../PNG/QuitButton.png"), TEXT("../../PNG/QuitButtonH.png"),
this, &TitleScreen::QuitGame);
}
void TitleScreen::Update(float dt, INPUTDATA* input)
{
}
void TitleScreen::Draw()
{
StartRender();
DrawSprite(&titleScreenBG, 0, titleScreenBG.position.x, titleScreenBG.position.y, titleScreenBG.position.z);
playButton.Draw();
quitButton.Draw();
EndRender();
}
// Public Methods
void TitleScreen::QuitGame()
{
CloseDirect3D();
}
void TitleScreen::NewGame()
{
CloseDirect3D();
}
If anyone has any advice on how I can make the buttons dynamic for any case in a different way, or know what this problem is, please help! :)
To get rid of the link error, move all method definitions starting with template from the .cpp file to the .h file. In your code, move these:
template <class t> void MENUBUTTON<t>::SetButton ... { ... }
template <class t> void MENUBUTTON<t>::Draw ... { ... }
The reason why it doesn't work with the .cpp file is that the compiler treats MENUBUTTON<Foo> and MENUBUTTON<Bar> etc. as different classes, and it generates and compiles such a class whenever it is used. So if you use MENUBUTTON<TitleScreen> when compiling titlescreen.cpp, then the MENUBUTTON<TitleScreen> code will be compiled into the object file titlescreen.o. But the methods SetButton and Draw will be missing at link time, because they are not defined in titlescreen.cpp or any of the .h files it includes. MenuButton.o won't contain it either, because MenuButton.cpp does not need MENUBUTTON<TitleScreen>.
Just to clarify the first answer, you can't have a template class that is declared in a header and then implemented in a separated compiled translation unit (i.e. .cpp file). You've got to put all the code in the header. You can either put it all in the initial class declaration, or using "inline" declare the class first with the functions, then implement the specific functions further down in the header.
Speaking of a better way ... why do you need a template here?
Plain old virtual function or pointer to member would do.
This would be a perfect application of the Command Design Pattern.
Templates give you compile-time polymorphism, while you are probably looking for run-time polymorphism here.