使用 dynamic_cast 检测派生 class 时指针出错
Error with pointer when using dynamic_cast to detect derived class
我想就我面临的问题寻求帮助。
我用 class Shape 和 Circle(派生自 shape)的多态程序进行了继承。所以我有一些这样的代码
main.cpp
Shape* shape = new (nothrow) Shape[size]();
input_circle(shape);
show_circle_area(shape);
还有 main.cpp 中的程序
void show_circle_area(Shape *mshape){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Circle*> (mshape[i]))
cout << mshape[i].getWidth() << " " << mshape[i].getArea() << " " << mshape[i].getPerimeter() << endl;
}
当我运行这个程序时,我总是得到这个错误:
main2.cpp: In function 'void output_circle(Shape*)':
main2.cpp:66:39: error: cannot dynamic_cast '*(mshape + ((sizetype)(((unsigned int)i) * 40u)))' (of type 'class Shape') to type 'class Circle*' (source is not a pointer)
if (dynamic_cast<Circle*> (mshape[i]))
^
任何人都可以帮助我解决这个问题?
main.cpp(更新)
#include "Shape.h"
#include "Circle.h"
#include "Rectangle.h"
#include "Square.h"
#include <fstream>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#include <limits>
#include <typeinfo>
using namespace std;
const int size = 200;
int totshape = 0;
// INPUT FROM FILE
void input_circle(Shape* mshape[]){
ifstream file;
int i;
double r;
file.open("circle.txt");
while (file >> r){
Circle* crl = new (nothrow) Circle(r);
mshape[totshape]=crl;
totshape++;
}
file.close();
}
void input_rectangle(Shape* mshape[]){
ifstream file;
int i;
double w,h;
file.open("rectangle.txt");
while (file >> w >> h){
Rectangle* rec = new (nothrow) Rectangle(w,h);
mshape[totshape]=rec;
totshape++;
}
file.close();
}
void input_square(Shape* mshape[]){
ifstream file;
int i;
double s;
file.open("square.txt");
while (file >> s){
Square* sqr = new (nothrow) Square(s);
mshape[totshape]=sqr;
totshape++;
}
file.close();
}
//OUTPUT TO FILE
void output_circle(Shape *mshape[]){
int i;
ofstream file;
file.open("outcircle.txt");
file << "radius\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Circle*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
void output_rectangle(Shape *mshape[]){
int i;
ofstream file;
file.open("outrectangle.txt");
file << "width\theight\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Rectangle*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getHeight() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
void output_square(Shape *mshape[]){
int i;
ofstream file;
file.open("outsquare.txt");
file << "sisi\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Square*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
//SORTING STL FOR AREA AND PERIMETER
bool sortByArea(Shape lhs[], Shape rhs[]) {
return lhs->getArea() < rhs->getArea();
}
bool sortByPerimeter(Shape lhs[], Shape rhs[]){
return lhs->getArea() < rhs->getArea();
}
//SHOW DATA SORT BY AREA
void show_shape_area(Shape *shape[]){
int i;
sort(shape,shape+totshape,sortByArea);
cout << "ALL SHAPE" << endl;
for (i=0;i<totshape;i++)
cout << shape[i]->getWidth() << " " << shape[i]->getWidth() << " " << shape[i]->getArea() << " " << shape[i]->getPerimeter() << endl;
}
void show_circle_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Circle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_rectangle_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "RECTANGLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Rectangle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getHeight() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_square_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "SQUARE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Square*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
//SHOW DATA SORT BY PERIMETER
void show_shape_perimeter(Shape *shape[]){
int i;
sort(shape,shape+totshape,sortByPerimeter);
cout << "ALL SHAPE" << endl;
for (i=0;i<totshape;i++)
cout << shape[i]->getWidth() << " " << shape[i]->getWidth() << " " << shape[i]->getArea() << " " << shape[i]->getPerimeter() << endl;
}
void show_circle_perimeter(Shape *mshape[]){
int i;
//Shape * tempshape;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
//cout << "masuk for" << endl;
//tempshape=&mshape[i];
if (dynamic_cast<Circle*> (mshape[i])){
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
//cout << "masuk" << endl;
}
}
void show_rectangle_perimeter(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "RECTANGLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Rectangle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getHeight() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_square_perimeter(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "SQUARE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Square*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
//ADD DATA
void add_circle(Shape *mshape[]){
int input;
cout << endl << "Masukkan jari-jari : ";
while (!(cin >> input) || input < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan jari-jari : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Circle* crl = new (nothrow) Circle(input);
mshape[totshape]=crl;
totshape++;
}
void add_rectangle(Shape *mshape[]){
int inwidth, inheight;
cout << endl << "Masukkan panjang : ";
while (!(cin >> inwidth) || inwidth < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan panjang : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
cout << endl << "Masukkan lebar : ";
while (!(cin >> inheight) || inheight < 0 || !(inheight < inwidth)) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan lebar : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Rectangle* rec = new (nothrow) Rectangle(inwidth,inheight);
mshape[totshape]=rec;
totshape++;
}
void add_square(Shape *mshape[]){
int input;
cout << endl << "Masukkan sisi : ";
while (!(cin >> input) || input < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan sisi : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Square* sqr = new (nothrow) Square(input);
mshape[totshape]=sqr;
totshape++;
}
//DELETE DATA
//MAIN PROGRAM
int main(){
Shape* shape[size];
input_circle(shape);
input_rectangle(shape);
input_square(shape);
show_shape_area(shape);
show_shape_perimeter(shape);
show_circle_area(shape);
show_circle_perimeter(shape);
show_rectangle_area(shape);
show_rectangle_perimeter(shape);
show_square_area(shape);
show_square_perimeter(shape);
//add_circle(shape);
//show_circle_area(shape);
//add_rectangle(shape);
//show_rectangle_area(shape);
//add_square(shape);
//show_square_area(shape);
output_circle(shape);
output_rectangle(shape);
output_square(shape);
return 0;
}
你的问题在这里:
mshape[totshape]=crl;
这个赋值只是将 crl
中的 "Shape part" 复制到 mshape[totshape]
因此 mshape[totshape]
仍然是一个形状,而不是一个圆。
为了解决您的问题,请使用 Shape* 指针数组而不是 Shape 值:
Shape* shape[size]; // we should write this as size is a const
而且,您的 input_***()
函数:
void input_circle(Shape* mshape[]){
ifstream file;
int i;
double r;
file.open("circle.txt");
while (file >> r){
Circle* crl = new Circle(r);
mshape[totshape]=crl;
totshape++;
}
file.close();
}
注意函数原型有变化,其他函数请照做,用mshape[i]->foo
代替mshape[i].foo
现在的演员表是:if (dynamic_cast<Circle*> (mshape[i])){
不要忘记在结束前释放内存,因为我们使用的是指针:
for (int i = 0; i < totshape; i++) delete mshape[i];
此删除将强制您使 Shape 的析构函数成为虚拟的:
class Shape {
public:
virtual ~Shape() {...}
}
否则,Circle、Rectangle ...的析构函数将不会被调用。
我想就我面临的问题寻求帮助。
我用 class Shape 和 Circle(派生自 shape)的多态程序进行了继承。所以我有一些这样的代码
main.cpp
Shape* shape = new (nothrow) Shape[size]();
input_circle(shape);
show_circle_area(shape);
还有 main.cpp 中的程序
void show_circle_area(Shape *mshape){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Circle*> (mshape[i]))
cout << mshape[i].getWidth() << " " << mshape[i].getArea() << " " << mshape[i].getPerimeter() << endl;
}
当我运行这个程序时,我总是得到这个错误:
main2.cpp: In function 'void output_circle(Shape*)':
main2.cpp:66:39: error: cannot dynamic_cast '*(mshape + ((sizetype)(((unsigned int)i) * 40u)))' (of type 'class Shape') to type 'class Circle*' (source is not a pointer)
if (dynamic_cast<Circle*> (mshape[i]))
^
任何人都可以帮助我解决这个问题?
main.cpp(更新)
#include "Shape.h"
#include "Circle.h"
#include "Rectangle.h"
#include "Square.h"
#include <fstream>
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#include <limits>
#include <typeinfo>
using namespace std;
const int size = 200;
int totshape = 0;
// INPUT FROM FILE
void input_circle(Shape* mshape[]){
ifstream file;
int i;
double r;
file.open("circle.txt");
while (file >> r){
Circle* crl = new (nothrow) Circle(r);
mshape[totshape]=crl;
totshape++;
}
file.close();
}
void input_rectangle(Shape* mshape[]){
ifstream file;
int i;
double w,h;
file.open("rectangle.txt");
while (file >> w >> h){
Rectangle* rec = new (nothrow) Rectangle(w,h);
mshape[totshape]=rec;
totshape++;
}
file.close();
}
void input_square(Shape* mshape[]){
ifstream file;
int i;
double s;
file.open("square.txt");
while (file >> s){
Square* sqr = new (nothrow) Square(s);
mshape[totshape]=sqr;
totshape++;
}
file.close();
}
//OUTPUT TO FILE
void output_circle(Shape *mshape[]){
int i;
ofstream file;
file.open("outcircle.txt");
file << "radius\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Circle*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
void output_rectangle(Shape *mshape[]){
int i;
ofstream file;
file.open("outrectangle.txt");
file << "width\theight\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Rectangle*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getHeight() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
void output_square(Shape *mshape[]){
int i;
ofstream file;
file.open("outsquare.txt");
file << "sisi\tarea\tperimeter" << endl;
for (i=0;i<totshape;i++){
if (dynamic_cast<Square*> (mshape[i]))
file << mshape[i]->getWidth() << "\t" << mshape[i]->getArea() << "\t" << mshape[i]->getPerimeter() << endl;
}
file.close();
}
//SORTING STL FOR AREA AND PERIMETER
bool sortByArea(Shape lhs[], Shape rhs[]) {
return lhs->getArea() < rhs->getArea();
}
bool sortByPerimeter(Shape lhs[], Shape rhs[]){
return lhs->getArea() < rhs->getArea();
}
//SHOW DATA SORT BY AREA
void show_shape_area(Shape *shape[]){
int i;
sort(shape,shape+totshape,sortByArea);
cout << "ALL SHAPE" << endl;
for (i=0;i<totshape;i++)
cout << shape[i]->getWidth() << " " << shape[i]->getWidth() << " " << shape[i]->getArea() << " " << shape[i]->getPerimeter() << endl;
}
void show_circle_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Circle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_rectangle_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "RECTANGLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Rectangle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getHeight() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_square_area(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByArea);
cout << "SQUARE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Square*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
//SHOW DATA SORT BY PERIMETER
void show_shape_perimeter(Shape *shape[]){
int i;
sort(shape,shape+totshape,sortByPerimeter);
cout << "ALL SHAPE" << endl;
for (i=0;i<totshape;i++)
cout << shape[i]->getWidth() << " " << shape[i]->getWidth() << " " << shape[i]->getArea() << " " << shape[i]->getPerimeter() << endl;
}
void show_circle_perimeter(Shape *mshape[]){
int i;
//Shape * tempshape;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "CIRCLE" << endl;
for (i=0;i<totshape;i++)
//cout << "masuk for" << endl;
//tempshape=&mshape[i];
if (dynamic_cast<Circle*> (mshape[i])){
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
//cout << "masuk" << endl;
}
}
void show_rectangle_perimeter(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "RECTANGLE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Rectangle*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getHeight() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
void show_square_perimeter(Shape *mshape[]){
int i;
sort(mshape,mshape+totshape,sortByPerimeter);
cout << "SQUARE" << endl;
for (i=0;i<totshape;i++)
if (dynamic_cast<Square*> (mshape[i]))
cout << mshape[i]->getWidth() << " " << mshape[i]->getArea() << " " << mshape[i]->getPerimeter() << endl;
}
//ADD DATA
void add_circle(Shape *mshape[]){
int input;
cout << endl << "Masukkan jari-jari : ";
while (!(cin >> input) || input < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan jari-jari : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Circle* crl = new (nothrow) Circle(input);
mshape[totshape]=crl;
totshape++;
}
void add_rectangle(Shape *mshape[]){
int inwidth, inheight;
cout << endl << "Masukkan panjang : ";
while (!(cin >> inwidth) || inwidth < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan panjang : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
cout << endl << "Masukkan lebar : ";
while (!(cin >> inheight) || inheight < 0 || !(inheight < inwidth)) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan lebar : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Rectangle* rec = new (nothrow) Rectangle(inwidth,inheight);
mshape[totshape]=rec;
totshape++;
}
void add_square(Shape *mshape[]){
int input;
cout << endl << "Masukkan sisi : ";
while (!(cin >> input) || input < 0) // <<< note use of "short circuit" logical operation here
{
cout << "Input tidak valid" << endl;
cout << "Masukkan sisi : ";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // NB: preferred method for flushing cin
}
Square* sqr = new (nothrow) Square(input);
mshape[totshape]=sqr;
totshape++;
}
//DELETE DATA
//MAIN PROGRAM
int main(){
Shape* shape[size];
input_circle(shape);
input_rectangle(shape);
input_square(shape);
show_shape_area(shape);
show_shape_perimeter(shape);
show_circle_area(shape);
show_circle_perimeter(shape);
show_rectangle_area(shape);
show_rectangle_perimeter(shape);
show_square_area(shape);
show_square_perimeter(shape);
//add_circle(shape);
//show_circle_area(shape);
//add_rectangle(shape);
//show_rectangle_area(shape);
//add_square(shape);
//show_square_area(shape);
output_circle(shape);
output_rectangle(shape);
output_square(shape);
return 0;
}
你的问题在这里:
mshape[totshape]=crl;
这个赋值只是将 crl
中的 "Shape part" 复制到 mshape[totshape]
因此 mshape[totshape]
仍然是一个形状,而不是一个圆。
为了解决您的问题,请使用 Shape* 指针数组而不是 Shape 值:
Shape* shape[size]; // we should write this as size is a const
而且,您的 input_***()
函数:
void input_circle(Shape* mshape[]){
ifstream file;
int i;
double r;
file.open("circle.txt");
while (file >> r){
Circle* crl = new Circle(r);
mshape[totshape]=crl;
totshape++;
}
file.close();
}
注意函数原型有变化,其他函数请照做,用mshape[i]->foo
代替mshape[i].foo
现在的演员表是:if (dynamic_cast<Circle*> (mshape[i])){
不要忘记在结束前释放内存,因为我们使用的是指针:
for (int i = 0; i < totshape; i++) delete mshape[i];
此删除将强制您使 Shape 的析构函数成为虚拟的:
class Shape {
public:
virtual ~Shape() {...}
}
否则,Circle、Rectangle ...的析构函数将不会被调用。