This question already has answers here:
Undefined reference to vtable
(21 answers)
Closed 6 years ago.
I try to implement examples of "C++ An Introduction To Programming" by Jesse Liberty and Tim Keogh but on implementing pure virtual functions is compiling but not building. It is giving the error : undefined reference to 'vtable for circle'
I have tried substituting the variable itsRadius for a virtual function GetItsRadius to see if it would work but it started giving me the same errors in the switch statement but for Rectangle and Square and also the same error as before for circle.
Here is the code:
#include <iostream>
using namespace std;
enum BOOL { FALSE, TRUE };
class Shape
{
public:
Shape(){}
~Shape(){}
virtual long GetArea() = 0; // error
virtual long GetPerim()= 0;
virtual void Draw() = 0;
private:
};
void Shape::Draw()
{
cout << "Abstract drawing mechanism!\n";
}
class Circle : public Shape
{
public:
Circle(int radius):itsRadius(radius){}
~Circle(){}
long GetArea() { return 3 * itsRadius * itsRadius; }
long GetPerim() { return 9 * itsRadius; }
void Draw();
private:
int itsRadius;
int itsCircumference;
};
class Rectangle : public Shape
{
public:
Rectangle(int len, int width):
itsLength(len), itsWidth(width){}
~Rectangle(){}
long GetArea() { return itsLength * itsWidth; }
long GetPerim() { return 2*itsLength + 2*itsWidth; }
virtual int GetLength() { itsLength; }
virtual int GetWidth() { itsWidth; }
void Draw();
private:
int itsWidth;
int itsLength;
};
void Rectangle::Draw()
{
for (int i = 0; i<itsLength; i++)
{
for (int j = 0; j<itsWidth; j++)
cout << "x ";
cout << "\n";
}
Shape::Draw();
}
class Square : public Rectangle
{
public:
Square(int len);
Square(int len, int width);
~Square(){}
long GetPerim() {return 4 * GetLength();}
};
Square::Square(int len):
Rectangle(len,len)
{}
Square::Square(int len, int width):
Rectangle(len,width)
{
if (GetLength() != GetWidth())
cout << "Error, not a square... a Rectangle??\n";
}
void startof()
{
int choice;
BOOL fQuit = FALSE;
Shape * sp;
while (1)
{
cout << "(1)Circle (2)Rectangle (3)Square (0)Quit: \n";
cin >> choice;
switch (choice)
{
case 1: sp = new Circle(5);
break;
case 2: sp = new Rectangle(4,6);
break;
case 3: sp = new Square (5);
break;
default: fQuit = TRUE;
break;
}
if (fQuit)
break;
sp->Draw();
cout << "\n";
}
}
int main()
{
startof();
}
The problem here is that you have not defined the function Circle::Draw(). If you define it the code compiles.
As an aside, you should make the Shape destructor virtual (otherwise instances of derived classes may not be properly destroyed in some cases). The rule here is that if a class has any virtual members the destructor should also be virtual.
I know the compilation message you see is quite cryptic. I have seen scenarios where this "undefined v-table" compiler error is a side-effect of some other problem, as in this case. Just to let you know, a good way to make this error go away is to move one of the virtual function definitions of the affected class out of line (I did this with the Circle destructor above, having made the Shape destructor virtual first). This revealed the true problem with a better compiler error.
Related
This code isn't compiled. All problems in virtual function attack() in basic class.
It hasn't got acces to massive in class Team. I was trying do theese classes friend.But it do not work whatever. Also I've done function ptr but it don't work.
Virtual function don't work in inherited classes too. Visual studio 2015 shows errors:
C2228, C2227, C2027.
Please help.
class Team;
class Unit
{
protected:
int hp;
int dmg;
int doodge;
public:
Unit(int hp, int dmg, int doodge): hp(hp), dmg(dmg), doodge(doodge){}
int GetHP()
{
return hp;
}
void SetHP(int hp)
{
this->hp = hp;
}
virtual void attack(Team &T)
{
int id = rand() % 3;
for (int i = 0; i < 3; i++)
if (typeid(*this) == typeid(T.arr[i]))
{
id = i;
break;
}
if (T.arr[id] <= 0)
return;
else
T.arr[id]->SetHP(T.arr[id]->GetHP() - this->dmg);
}
};
class Swordsman:public Unit
{
public:
Swordsman():Unit(15,5,60){}
//virtual void attack(Team & T)override
//{
// int id = rand() % 3;
// for (int i = 0; i < 3; i++)
// if (typeid(Swordsman) == typeid())
// {
// id = i;
// break;
// }
// if (*T.arr[id]->GetHP <= 0)
// return;
// else
// *T.arr[id]->SetHP(T.arr[id]->GetHP() - dmg);
//}
};
class Archer :public Unit
{
public:
Archer() :Unit(12, 4, 40) {}
//virtual void attack(Team & T)override
//{
// int id = rand() % 3;
// for (int i = 0; i < 3; i++)
// if (typeid(Archer) == typeid())
// {
// id = i;
// break;
// }
// if (*T.arr[id]->GetHP <= 0)
// return;
// else
// *T.arr[id]->SetHP(T.arr[id]->GetHP() - dmg);
//}
};
class Mage :public Unit
{
public:
Mage() :Unit(8, 10, 30) {}
/*virtual void attack(Team & T)override
{
int id = rand() % 3;
for (int i = 0; i < 3; i++)
if (typeid(*this) == typeid())
{
id = i;
break;
}*/
};
class Team
{
static short counter;
string name;
Unit* arr[3];
public:
Team()
{
name = "Team " + counter++;
for (int i = 0; i < 3; i++)
{
int selecter = rand() % 3;
switch (selecter)
{
case 0:
arr[i] = new Swordsman();
break;
case 1:
arr[i] = new Archer();
break;
case 2:
arr[i] = new Mage();
break;
}
}
}
~Team()
{
delete[]arr;
}
Unit * ptr(int id)
{
return arr[id];
}
bool check()
{
bool res = false;
for (int i = 0; i < 3; i++)
if (arr[i]->GetHP() > 0)
res = true;
return res;
}
void print()
{
cout << endl << "\t\t" << name << endl << endl;
cout << "\t" << typeid(*arr[0]).name() << endl;
cout << "\t" << typeid(*arr[1]).name() << endl;
cout << "\t" << typeid(*arr[2]).name() << endl;
}
friend class Unit;
};
short Team::counter = 0;
class Game
{
Team A, B;
public:
int Play()
{
while (true)
{
A.ptr(1)->attack(B);
if (A.check())
return 1;
else if (B.check())
return 2;
}
}
};
int main()
{
return 0;
}
Omitting anything irrelevant:
class Team;
class Unit
{
public:
virtual void attack(Team &T)
{
if(typeid(*this) == typeid(T.arr[i]))
// ^^^
{ }
}
};
You are accessing a member of class Team, but at the time given, you only have provided the declaration of Team... Side note: this is not specific to virtual functions, but would occur with any code you write.
Your problem now is that function implementations of both classes Team as well as Unit rely on the complete definition of the other class. So only solution to the problem is to implement one of the functions outside the class, e. g.:
class Team;
class Unit
{
public:
// requires Team, so only declared, not implemented!
virtual void attack(Team &T);
// ^
};
class Team
{
// complete definition!
};
void Unit::attack(Team& t)
{
// now implementation of...
}
Another minor problem is that arr member is private. Well, you provided a getter already (ptr), so use it (and give it a better name...).
If you want to go further towards a clean design, split your units and the team into different compilation units, each coming with a header and a source file:
unit.h:
class Team;
class Unit
{
// private members
public:
// only declarations as above, including constructor/destructor
// by the way: you are lacking a virtual destructor!!!
virtual ~Unit();
};
unit.cpp:
#include "unit.h"
#include "team.h" // fetch the definition of Team!
Unit(/*...*/) { }
Unit::~Unit() { }
// function definitions as shown above...
You would do the same for Team and even your Unit derived classes as well as the Game class. Be aware, though, that you need the complete class definition available if you want to inherit, so you need to include unit.h already int the headers:
archer.h:
#include "unit.h"
class Archer : public Unit
{
// again, only function declarations...
// as base class has already a virtual destructor, own destructor
// gets virtual implicitly (even the default one), so if you do
// not need it, you do not have to define it...
};
archer.cpp:
#include "archer.h"
// and whatever else needed, solely, unit.h already comes with archer.h
// implementations...
I dont understand the diffrence between Polymorphism and Inheritance... They Litterarly do the same thing...
Simple Example Of Polymorphism:
class shape {
public:
void setValues(int height_, int width_) {
height = height_, width = width_;
}
protected:
int height, width;
private:
};
class rectangle :public shape, public ThreeDView{
public:
int area() {
return(shape::height*shape::width);
}
float threeDArea() {
return(((shape::height*shape::width)/2)*(std::cos(Z_LENGTH)));
}
};
class ThreeDView{
public:
void setZLength(int value) {
Z_LENGTH = value;
}
int setCompact(bool ans) {
compact = ans;
}
float getZLength() {
return Z_LENGTH;
}
bool getCOMPACT() {
return compact;
}
protected:
float Z_LENGTH;
bool compact;
private:
unsigned char ZCHAR = 'Z';
};
class triangle :public shape {
public:
int area() {
return((shape::height * shape::width) / 2);
}
};
int main(){
rectangle rect2;
triangle trng2;
shape *poly = &rect2;
shape *poly2 = &trng2;
poly->setValues(2,3);
poly2->setValues(5,4);
std::cout << "AREA : " << trng1.area() << "AREA RECT : \n" <<rect1.area() << std::endl;
}
Above example translated to Inheritance:
class shape {
public:
void setValues(int height_, int width_) {
height = height_, width = width_;
}
protected:
int height, width;
private:
};
class rectangle :public shape, public ThreeDView{
public:
int area() {
return(shape::height*shape::width);
}
float threeDArea() {
return(((shape::height*shape::width)/2)*(std::cos(Z_LENGTH)));
}
};
class triangle :public shape {
public:
int area() {
return((shape::height * shape::width) / 2);
}
};
int main(){
rectangle rect2;
triangle trng2;
rect2.setValues(2,3);
trng2.setValues(5,4);
std::cout << "AREA : " << trng1.area() << "AREA RECT : \n" <<rect1.area() << std::endl;
}
Please tell me diffrence. Honestly i dont even see the use of Polymorphism! Thanks for helping!
Here's a version of your first example, that actually uses polymorphism:
#include <iostream>
#include <string>
class shape
{
public:
void setValues(int height_, int width_)
{
height = height_;
width = width_;
}
virtual int area() = 0; // This is needed for polymorphism to work
virtual std::string name() = 0;
protected:
int height;
int width;
};
class rectangle : public shape
{
public:
int area()
{
return height * width;
}
std::string name()
{
return "Rectangle";
}
};
class triangle :public shape
{
public:
int area()
{
return height * width / 2;
}
std::string name()
{
return "Triangle";
}
};
void print_area(shape& poly)
{
std::cout << poly.name() << ' ' << poly.area() << '\n';
}
int main()
{
rectangle rect;
triangle trng;
rect.setValues(2, 3);
trng.setValues(5, 4);
print_area(rect);
print_area(trng);
}
The first big change is that I declare the virtual function area in the shape class. For polymorphism to work, the functions must be declared in the base class as virtual. The "assignment" to 0 is simply telling the compiler that it's an abstract function, and the child-classes must override that function.
The second big change is that I use a function to print the area, one that only takes a reference to the base shape class. You must use references or pointers to the base class for polymrphism to work, not use the actual objects directly like in your example.
This works as expected.
I'd like to access to a double pointer which is located in another class "Board".
class Board
{
public:
Board(void);
Board(unsigned int xSize, unsigned int ySize);
~Board(void);
void SetObjectManager(ObjectManager* pObm);
void SetBlock(Block* block);
void LoadBoard(void);
void InitBoard(void);
//Other Functions...
private:
ObjectManager* m_obm;
Block* m_block;
//pointer to pointer to a int. (for 2 dimensional-array)
int **m_board;
};
First, the Board class. at the last line of class, you can see m_board.
I want to change this value in outside of this class.
Like this,
void Block::InitBlock(void)
{
int randPiece = Random::GIRand().RandInt(0, 1);
int randPos = Random::GIRand().RandInt(0, 10);
switch (randPiece)
{
case 0:
m_piece[2][1] = 1;
m_piece[2][2] = 1;
m_piece[2][3] = 1;
m_piece[3][3] = 1;
break;
//Other cases are here...
}
std::cout << "RandPos : " << randPos << std::endl;
std::cout << "RandPiece : " << randPiece << std::endl;
for (int y = 0; y < m_ySize; ++y)
{
for (int x = 0, pX = randPos; x < m_xSize; ++x, ++randPos)
{
if (m_piece[x][y] != 0)
m_board->SetBoardStatus(randPos, y, 1);
}
}
}
But, When I run this program, It blows up at SetBoardStatus(int, int, int)
SetBoardStatus looks like this,
void Board::SetBoardStatus(int x, int y, int value)
{
m_board[x][y] = value; //Visual Studio breaks the program here.
}
I allocate the double pointer properly.
And I set the board at the outside of this classes.
void Block::SetBoard(Board* board)
{
m_board = board;
}
And this is my block class.
class Block
{
public:
Block(void);
~Block(void);
void SetObjectManager(ObjectManager* pObm);
void LoadBlock (void);
void InitBlock (void);
void UpdateBlock (void);
void ReleaseBlock (void);
void SetBoard(Board* board);
private:
ObjectManager* m_obm;
Board* m_board;
int **m_piece;
int m_xSize;
int m_ySize;
};
Consider inheriting Block in Board; This will eliminate any possible de-referencing errors or bugs, as you can access the pointer right away.
I am trying to compile several files together for an agent based simulation of a zombie apocalypse (Awesome, right!?) Anyway, I am getting an error that I think has to do with the order in which header files are being included, but I can't wrap my head around how to figure out what's going wrong and how to fix it. The exact error is: "In file included from main.cpp, field 'Location' has incomplete type." Then similarly, "In constructor Creature::Creature() 'Location' undeclared".
Here are my files:
definitions.h
#ifndef definitions_h
#define definitions_h
class Creature;
class Item;
class Coords;
class Grid
{
public:
Creature*** cboard;
Item*** iboard;
Grid(int WIDTH, int HEIGHT);
void FillGrid(int H, int Z); //initializes grid object with humans and zombies
void Refresh(); //calls Creature::Die(),Move(),Attack(),Breed() on every square
void UpdateBuffer(char** buffer);
bool isEmpty(int startx, int starty, int dir);
};
class Random
{
public:
int* rptr;
void Print();
Random(int MIN, int MAX, int LEN);
~Random();
private:
bool alreadyused(int checkthis, int len, int* rptr);
bool isClean();
int len;
};
class Creature
{
public:
bool alive;
Coords Location;
char displayletter;
Creature() {Location.x=0; Location.y=0;} //ERROR HERE
Creature(int i, int j) {Location.xvalue(i); Location.yvalue(j);}
virtual void Attack();
virtual void Breed();
virtual void Move(Creature*** cboard);
virtual void Die();
virtual void MoveTo(Creature*** cboard, int dir);
virtual int DecideSquare(Creature*** cboard);
};
class Human : public Creature
{
public:
bool armed; //if armed, chances of winning fight increased for next fight
bool vaccinated; //if vaccinated, no chance of getting infected
int bitecount; //if a human is bitten, bite count is set to a random number
int breedcount; //if a human goes x steps without combat, will breed if next to a human
int starvecount; //if a human does not eat in x steps, will die
void Attack(Creature*** cboard);
void Breed(Creature*** cboard); //will breed after x steps and next to human
void Move(Creature*** cboard); //moves and checks itemboard for food
void Die(); //depends on bitecount, starvecount, and bool alive
void MoveTo(Creature*** cboard, int dir);
int DecideSquare(Creature*** cboard) {Creature::DecideSquare(Creature*** cboard);}
};
class Zombie : public Creature
{
public:
Zombie(int i, int j) {Creature::Creature()};
void Attack(Creature*** cboard); //will attack any adjacent human
void Breed() {} //does nothing
void Move(Creature*** cboard) {Creature::Move(Creature*** cboard;}
void Die(); //can only die from being attacked, never starves
};
class Item
{
};
class Coords
{
public:
int x;
int y;
int MaxX;
int MaxY;
Coords() {x=0; y=0; MaxX=0; MaxY=0;}
Coords(int X, int Y, int WIDTH, int HEIGHT) {x=X; y=Y; MaxX=WIDTH; MaxY=HEIGHT; }
void MoveRight();
void MoveLeft();
void MoveUp();
void MoveDown();
void MoveUpRight();
void MoveUpLeft();
void MoveDownRight();
void MoveDownLeft();
void MoveDir(int dir);
void setx(int X) {x=X;}
void sety(int Y) {y=Y;}
};
#endif
main.cpp
#include <cstdlib>
#include <iostream>
#include "definitions.h"
using namespace std;
int main(int argc, char *argv[])
{
system("PAUSE");
return EXIT_SUCCESS;
}
definitions.cpp
#include <cstdlib>
#include "definitions.h"
Grid::Grid(int WIDTH, int HEIGHT)
{
//builds 2d array of creature pointers
cboard = new Creature**[WIDTH];
for(int i=0; i<WIDTH; i++)
{
cboard[i] = new Creature*[HEIGHT];
}
//builds 2d array of item pointers
iboard = new Item**[WIDTH];
for (int i=0; i<WIDTH; i++)
{
iboard[i] = new Item*[HEIGHT];
}
}
void Grid::FillGrid()
{
/* For each creature pointer in grid, randomly selects whether to initalize
as zombie, human, or empty square. This methodology can be changed to initialize
different creature types with different probabilities */
int random;
for (int i=0; i<WIDTH; i++)
{
for (int j=0; j<HEIGHT; j++)
{
Random X(1,100,1); //create a single random integer from [1,100] at X.rptr
random=X->rptr;
if (random < 20)
cboard[i][j] = new Human(i,j);
else if (random < 40)
cboard[i][j] = new Zombie(i,j);
else
cboard[i][j] = NULL;
}
} //at this point every creature pointer should be pointing to either
//a zombie, human, or NULL with varying probabilities
}
void Grid::UpdateBuffer(char** buffer)
{
for (int i=0; i<WIDTH; i++)
{
for (int j=0; j<HEIGHT; j++)
{
if (cboard[i][j])
buffer[i][j]=cboard[i][j]->displayletter;
else
buffer[i][j]=' ';
}
}
}
bool Grid::isEmpty(int startx, int starty, int dir)
{
Coords StartLocation(startx,starty,WIDTH,HEIGHT);
switch(dir)
{
case 1:
StartLocation.MoveUp();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 2:
StartLocation.MoveUpRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 3:
StartLocation.MoveRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 4:
StartLocation.MoveDownRight();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 5:
StartLocation.MoveDown();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 6:
StartLocation.MoveDownLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 7:
StartLocation.MoveLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
case 8:
StartLocation.MoveUpLeft();
if (cboard[StartLocation.x][StartLocation.y])
return 0;
}
return 1;
}
void Coords::MoveRight() {(x==MaxX)? (x=0):(x++);}
void Coords::MoveLeft() {(x==0)? (x=MaxX):(x--);}
void Coords::MoveUp() {(y==0)? (y=MaxY):(y--);}
void Coords::MoveDown() {(y==MaxY)? (y=0):(y++);}
void Coords::MoveUpRight() {MoveUp(); MoveRight();}
void Coords::MoveUpLeft() {MoveUp(); MoveLeft();}
void Coords::MoveDownRight() {MoveDown(); MoveRight();}
void Coords::MoveDownLeft() {MoveDown(); MoveLeft();}
void Coords::MoveDir(int dir)
{
switch(dir)
{
case 1:
MoveUp();
break;
case 2:
MoveUpRight();
break;
case 3:
MoveRight();
break;
case 4:
MoveDownRight();
break;
case 5:
MoveDown();
break;
case 6:
MoveDownLeft();
break;
case 7:
MoveLeft();
break;
case 8:
MoveUpLeft();
break;
case 0:
break;
}
}
Your forward declaration of class Coords in definitions.h is not enough to declare a variable of type Coords.
The forward declaration introduces the type but leaves it incomplete. You can declare a variable with pointer to incomplete type, but not a variable with incomplete type. So you must move the definition of class Coords before the definition of class Creature.
If you find yourself with a circular declaration dependency, you must introduce a pointer or reference declarator to solve it.
When a variable is declared, its type must be known. In your case, this means the definition of Coords must precede its use in the declaration Coords Location;.
Look at it from the compiler's perspective: it needs to know how much space Location will take, and for this it needs to know the definition of Coords. And of course, it's parsing from top to bottom.
I have created a code in C++ that is supposed to display an O and an X, and you can move the O with w/a/s/d, and the X moves randomly. It compiles fine, but when I run it, there is an O, but no X. I put the source code here:
#include <iostream>
using namespace std;
//program class: defines player, enemies and powerups
#include<stdlib.h>
#include<time.h>
class prgm
{
friend void set_pos(prgm*const nprgm,int px,int py){nprgm->x=px;nprgm->y=py;}
friend void set_pos(prgm*const nprgm,int px,int py,int php){nprgm->x=px;nprgm->y=py;nprgm->hp=php;}
friend void set_pos(prgm*const nprgm,int px,int py,int php,char psym){nprgm->x=px;nprgm->y=py;nprgm->hp=php;nprgm->sym=psym;}
protected:
int x; //x-position
int y; //y-position
int hp; //health
char sym; //single-character representation
public:
prgm(){sym=' ';}
prgm(int px,int py,int php,char psym):x(px),y(py),hp(php),sym(psym){};
const int xpos(){return x;}
const int ypos(){return y;}
const char rsym(){return sym;}
void up(int n){y-=n;} //move program up
void left(int n){x-=n;} //move program left
void down(int n){y+=n;} //move program down
void right(int n){x+=n;} //move program right
void mutate(char nsym){sym=nsym;} //change program's symbol
void harm(int dam){hp-=dam;}
void heal(int dam){hp+=dam;}
prgm &prgm::operator=(const prgm&nprgm){x=nprgm.x;y=nprgm.y;hp=nprgm.hp;sym=nprgm.sym;}
};
//null program
prgm null();
//abstract enemy class for individual ai of each enemy
class enemy:public prgm
{
public:
void move(){}; //what enemy will do during its move
};
prgm player(0,0,0,'O');
void pmove()
{
char move;
cin>>move;
switch(move)
{
case 'w':
player.up(1);
break;
case 'a':
player.left(1);
break;
case 's':
player.down(1);
break;
case 'd':
player.right(1);
break;
case 'q':
exit(0);
break;
}
return;
}
//the X1 Virus Component, the simplest version of Virus X: moves in random directions, harms on contact.
class X1:public enemy
{
static const char sym='X';
public:
X1(){}
X1(int px,int py){x=px;y=py;}
void move();
};
void X1::move()
{
srand(time(0));
int dir=(rand()%2);
int dis=(rand()%3)-1;
while(dis=0)
{
dis=(rand()%3)-1;
}
if(dir=0)
{
y+=dis;
}
if(dir=1)
{
x+=dis;
}
return;
}
//sector 1
const int maxx=10; //length of sector
const int maxy=10; //height of sector
char sector[maxx][maxy]; //sector declaration
const int rsize=4;
prgm reactive_items[rsize];//array of powerups
X1 a(4,4); //enemy(ies)
const int vsize=1;
X1 viruses[vsize]={a}; //array of enemies
int px=0,py=0,php=1; //players position and hp
//function zeros-out the sector
void clear_sect()
{
for(int i=0;i<maxy;i++)
{
for(int j=0;j<maxx;j++)
{
sector[j][i]=' ';
}
}
}
//function sets all the enemies/powerups/player in the sector
void set_sect()
{
for(int i=0;i<rsize;i++)
{
int*tx=new int(reactive_items[i].xpos());
int*ty=new int(reactive_items[i].ypos());
char*ts=new char(reactive_items[i].rsym());
sector[*tx][*ty]=*ts;
delete tx;
delete ty;
delete ts;
}
for(int j=0;j<vsize;j++)
{
int*tx=new int(viruses[j].xpos());
int*ty=new int(viruses[j].ypos());
char*ts=new char(viruses[j].rsym());
sector[*tx][*ty]=*ts;
delete tx;
delete ty;
delete ts;
}
int*tx=new int(player.xpos());
int*ty=new int(player.ypos());
char*ts=new char(player.rsym());
sector[*tx][*ty]=*ts;
delete tx;
delete ty;
delete ts;
}
//function displays sector
void display_sect()
{
for(int i=0;i<maxy;i++)
{
for(int j=0;j<maxx;j++)
{
cout<<sector[j][i];
}
cout<<endl;
}
return;
}
void vmove()
{
for(int i=0;i<vsize;i++)
{
viruses[i].move();
}
return;
}
int main()
{
//load the sector # from the .txt, load the sector
set_pos(&player,px,py,php); //set the players x and y values
while(true){//while the player is on this sector
clear_sect();//clear the sector map
set_sect();//use the set function
display_sect();//use the display function
pmove();//players move
vmove();//enemy-ai move
//check board; relocate whats needed, initiate powerups, etc.
}//end of while
//when player wins sector
//write current sector to a .txt
//load program: restart this/story program/APHQ
return 0;
}
I know its long and pretty convoluted, (they were originally seperate .h files, but i put them together so that I could see all the code at once) but I really need an answer. Thanks
Your default constructor to prgm() sets the sym member to ' '. The static const char field does not override the base sym member, so the character used is probably the ' '.
Your enemy constructor should actually call the (int,int,int,char) base constructor to set the sym member.
Check your X1 class. It declares a static const char sym while it inherits a protected char sym member variable from class pgrm. Your display_sect function uses prgm's rsym() method, which returns the member variable, not the static member.