我在类Shape中有一个虚函数printShape(),并且有一个Rect,Line和Circle类,它会覆盖它,然后我创建一个Shapes数组(Shape **)并保存派生对象,但是当我遍历数组时数组中的每个派生对象都从形状调用函数printShape()而不是它覆盖的函数。这是我的Shape和Rectangle类以及我创建并填充Shape数组的TextManager类。不要注意编写代码的其他部分有多糟糕。
Shape.h:
#ifndef SHAPE
#define SHAPE
class Shape
{
public:
Shape();
virtual ~Shape();
virtual void printShape()const;
virtual bool isWithin(const Shape*) const;
virtual void translate(double,double);
public:
void setFill(const char*);
const char* getFill() const;
private:
char fill[10];
};
#endif
Rect.h:
#ifndef RECT
#define RECT
#include "Shape.h"
class Rect :public Shape
{
public:
Rect();
Rect(double, double, unsigned int, unsigned int);
virtual ~Rect();
public:
virtual bool isWithin(char* name, double x, double y, double ) const;
virtual bool isWithin(char* name, double x, double y, unsigned int w, unsigned int h) const;
virtual void translate(double,double);
void printShape()const;
public:
void setX(double);
void setY(double);
void setWidth(unsigned int);
void setHeight(unsigned int);
double getX();
double getY();
unsigned int getWidth();
unsigned int getHeight();
private:
double x, y;
unsigned int width, height;
};
#endif
Rect.cpp:
#include "Rect.h"
#include <iostream>
void Rect::setX(double x)
{
this->x = x;
}
void Rect::setY(double y)
{
this->y = y;
}
void Rect::setWidth(unsigned int w)
{
this->width = w;
}
void Rect::setHeight(unsigned int h)
{
this->height = h;
}
double Rect::getX()
{
return this->x;
}
double Rect::getY()
{
return this->y;
}
unsigned int Rect::getWidth()
{
return this->width;
}
unsigned int Rect::getHeight()
{
return this->height;
}
Rect::Rect()
{
this->x = 0;
this->y = 0;
this->width = 0;
this->height = 0;
}
Rect::Rect(double X,double Y, unsigned int W, unsigned int H)
{
setX(X);
setY(Y);
setWidth(W);
setHeight(H);
}
Rect::~Rect()
{
}
void Rect::printShape()const
{
std::cout << "rectangle ";
std::cout
<< this->x << " "
<< this->y << " "
<< this->width << " "
<< this->height << " ";
std::cout<<getFill();
}
bool Rect::isWithin(char* name, double x, double y, unsigned int w, unsigned int h) const
{
return !((this->x < x) || (this->y < y) || (this->width + this->x >(w + x)) || (this->height + this->y >(h + y)));
}
bool Rect::isWithin(char* name, double x, double y, double rad) const{
return ((this->x < x + rad) || this->x > x - rad) && (this->y < y + rad) || this->y > y - rad &&
(this->x+width < x + rad) || (this->x+width > x - rad) && (this->y < y + rad) || (this->y > y - rad) &&
(this->x + width < x + rad) || (this->x + width > x - rad) && (this->y+height < y + rad) || (this->y+height > y - rad) &&
(this->x < x + rad) || (this->x > x - rad) && (this->y + height < y + rad) || (this->y + height > y - rad);
}
void Rect::translate(double vertical, double horizontal)
{
x += horizontal;
y += vertical;
}
我有一个ManageText类,它从svg文件中读取数据,并用一个名为readFile()的函数填充数组
#ifndef MANAGETEXT
#define MANAGETEXT
#include "Shape.h"
#include "Rect.h"
class ManageText
{
public:
ManageText();
~ManageText();
public:
void readFile(const char*);
void writeFile(const char*);
public:
int findSvg(const char*);
void insertLine(const char* line, int row);
void removeLine(const char*, int row);
char* getLineFile(int);
void setLine(const char*, int);
void eraseShape(int);
void printShapes(const char* nameFile) const;
void translateShapes(double, double);
void createRect(double x, double y, unsigned int w, unsigned int h, const char* f, int row, const char*);
void createCircle(double x, double y, double r, const char* f, int row, const char*);
void createLine(double x1, double y1, double x2, double y2, int row, const char*);
public:
int getNumberLines();
void setNumberLines(char* nameFile);
int getSizeofFile(char* nameFile);
char* getNameFile();
char** getText();
int getShapesSize(const char* fileName) const;
private:
void clear();
int getLinesFromFile(const char*);
private:
char* nameFile;
char** text;
int numberLines;
Shape** shapes;
int shapesSize;
};
#endif
ManageText.cpp中的readFile():
void ManageText::readFile(const char* nameFile)
{
std::ifstream file;
file.open(nameFile, std::ios::in);
if (!file.is_open())
{
std::cout << "error";
return;
}
else
{
//read number of figures
int cntShapes = getShapesSize(nameFile);
shapes = new Shape*[cntShapes];
char shape[500000];
char toNum[15];
int tmp = 0;
while (!file.eof())
{
file >> shape;
if (strcmp(shape, "<rect") == 0)
{
Rect rect;
double x;
double y;
unsigned int w, h;
file >> toNum;
int nx = strlen(toNum);
for (int i = 3; i < nx; i++)
{
toNum[i - 3] = toNum[i];
}
x = atof(toNum);
rect.setX(x);
file >> toNum;
int ny = strlen(toNum);
for (int i = 3; i < ny; i++)
{
toNum[i - 3] = toNum[i];
}
y = atof(toNum);
rect.setY(y);
file >> toNum;
int nw = strlen(toNum);
for (int i = 7; i < nw; i++)
{
toNum[i - 7] = toNum[i];
}
w = atof(toNum);
rect.setWidth(w);
file >> toNum;
int nh = strlen(toNum);
for (int i = 8; i < nw; i++)
{
toNum[i - 8] = toNum[i];
}
h = atof(toNum);
rect.setHeight(h);
file >> toNum;
int nFill = strlen(toNum);
for (int i = 6; i < nFill; i++)
{
toNum[i - 6] = toNum[i];
}
toNum[nFill - 7] = '\0';
rect.setFill(toNum);
shapes[tmp] = ▭
tmp++;
}
else if (strcmp(shape, "<circle")==0)
{
Circle circle;
double x, y, r;
file >> toNum;
int nx = strlen(toNum);
for (int i = 4; i < nx; i++)
{
toNum[i - 4] = toNum[i];
}
x = atof(toNum);
circle.setX(x);
file >> toNum;
int ny = strlen(toNum);
for (int i = 4; i < ny; i++)
{
toNum[i - 4] = toNum[i];
}
y = atof(toNum);
circle.setY(y);
file >> toNum;
int nr = strlen(toNum);
for (int i = 3 ; i < nr; i++)
{
toNum[i - 3] = toNum[i];
}
r = atof(toNum);
circle.setRadius(r);
file >> toNum;
int nFill = strlen(toNum);
for (int i = 6; i < nFill; i++)
{
toNum[i - 6] = toNum[i];
}
toNum[nFill - 7] = '\0';
circle.setFill(toNum);
shapes[tmp] = &circle;
tmp++;
}
else if (strcmp(shape, "<line") == 0)
{
Line line;
double x1, y1, x2, y2;
file >> toNum;
int nx1 = strlen(toNum);
for (int i = 4; i < nx1; i++)
{
toNum[i - 4] = toNum[i];
}
x1 = atof(toNum);
line.setX1(x1);
file >> toNum;
int ny1 = strlen(toNum);
for (int i = 4; i < ny1; i++)
{
toNum[i - 4] = toNum[i];
}
y1 = atof(toNum);
line.setY1(y1);
file >> toNum;
int nx2 = strlen(toNum);
for (int i = 4; i < nx2; i++)
{
toNum[i - 4] = toNum[i];
}
x2 = atof(toNum);
line.setX2(x2);
file >> toNum;
int ny2 = strlen(toNum);
for (int i = 4; i < ny2; i++)
{
toNum[i - 4] = toNum[i];
}
y2 = atof(toNum);
line.setY2(y2);
file >> toNum;
int nFill = strlen(toNum);
for (int i = 6; i < nFill; i++)
{
toNum[i - 6] = toNum[i];
}
toNum[nFill - 7] = '\0';
line.setFill(toNum);
shapes[tmp] = &line;
tmp++;
}
}
}
}
所以我的问题是为什么不是来自shapes数组的每个对象都调用它自己的printShape函数,而是来自Shape类的那个?
答案 0 :(得分:3)
您正在调用printShape()的对象不再存在
{
Rect rect;
...
shapes[tmp] = ▭
} // Oops, rect was local and the reference is no longer valid
顺便说一下,最好使用std::vector< std::unique_ptr<Shape> >
代替new Shape*[cntShapes]
std::vector< std::unique_ptr<Shape> > shapes;
// ...
{
std::unique_ptr<Rect> pRect(new Rect);
// or use std::make_unique<Rect>() if you have C++14
// ...
pRect->SetX(x);
// ...
shapes.push_back(std::move(pRect));
}