请教C++类型指针转换的问题

silent_missile 2012-05-24 10:18:51
实际工作中遇到的问题,有一个计算,因为输入参数不同会产生不同的对象,比如三角形、四边形、五边形,于是设计了3个类
class sanjiaoxing
{
public:
virtual bool input(vector<double> in);
virtual double area();
protected:
point p1, p2, p3;
}

class sibianxing:public sanjiaoxing
{
public:
virtual bool input(vector<double> in);
virtual double area();
protected:
point p4;
}

class wubianxing:public sibianxing
{
public:
virtual bool input(vector<double> in);
virtual double area();
protected:
point p5;
}

由于用户输入的不同,将生成不同的形状,为了计算它们的面积我设定了一个指向对象的指针*ptr,并用ptr->area()来获得面积,但是问题在于ptr在初始化时应该怎么处理呢?

我的思路是先把*ptr定义为wubianxing,但是dynamic_cast不能改变一个指针的类型,只能把一个父类指针par的地址传递给另一个子类指针chi,而chi=par这个表达式编译通不过。

如果针对不同的输入、不同的形状分别写代码,那这个代码量就太大了,现在还只有3层继承关系,如果是30层,非得折磨死我不可。

哪位老鸟能给俺点指点?先谢过了
...全文
841 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
pathuang68 2012-05-25
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

谢谢,6楼的方法已经解决了我的问题

更进一步的,如果除了一次判断以外,还需要类型转换的话,可以使用先delete再new的方法,dynamic_cast实践检验不太好使。
[/Quote]

用dynamic_cast向上转型(把派生类指针转型为基类指针)总是可以的,向下转型则有可能报错。
pathuang68 2012-05-24
  • 打赏
  • 举报
回复
如果纯粹研究有继承体系的指针类型转换,不用考虑工厂模式,那样会使得事情变得更加复杂。

不过楼主的问题的确比较适合用工厂模式来解决,可以参考下面的代码:

#include <iostream>
#include <vector>
#include <cmath>
using namespace std;

// 定义一个“点”类
class Point
{
private:
double x;
double y;
public:
Point()
{
x = 0.0;
y = 0.0;
}

Point(double x, double y)
{
this->x = x;
this->y = y;
}

void set_X(double x)
{
this->x = x;
}

double get_X()
{
return x;
}

void set_Y(double y)
{
this->y = y;
}

double get_Y()
{
return y;
}
};

// 定义几何图形类
class Geometry
{
protected:
vector<Point> points;
public:
virtual double calculateArea() = 0;
virtual ~Geometry(){};
};

// 定义具体的几何图形类:三角形
class Triangle : public Geometry
{
public:
Triangle()
{
points.push_back(Point(0.0, 0.0));
points.push_back(Point(0.0, 0.0));
points.push_back(Point(0.0, 0.0));
}

Triangle(const Point& a, const Point& b, const Point& c)
{
points.push_back(a);
points.push_back(b);
points.push_back(c);
}

double calculateArea()
{
double line1 = sqrt(pow((points[0].get_X() - points[1].get_X()), 2.0) + pow((points[0].get_Y() - points[1].get_Y()), 2.0));
double line2 = sqrt(pow((points[1].get_X() - points[2].get_X()), 2.0) + pow((points[1].get_Y() - points[2].get_Y()), 2.0));
double line3 = sqrt(pow((points[2].get_X() - points[0].get_X()), 2.0) + pow((points[2].get_Y() - points[0].get_Y()), 2.0));
double halfPerimeter = (line1 + line2 + line3) / 2.0;
return sqrt(halfPerimeter * (halfPerimeter - line1) * (halfPerimeter - line2) * (halfPerimeter - line3));
}
};

// 定义具体的几何图形类:四边形
class Quadrangle : public Geometry
{
public:
Quadrangle()
{
points.push_back(Point(0.0, 0.0));
points.push_back(Point(0.0, 0.0));
points.push_back(Point(0.0, 0.0));
points.push_back(Point(0.0, 0.0));
}

Quadrangle(const Point& a, const Point& b, const Point& c, const Point& d)
{
points.push_back(a);
points.push_back(b);
points.push_back(c);
points.push_back(d);
}

double calculateArea()
{
double area = 0;
double line1 = sqrt(pow((points[0].get_X() - points[1].get_X()), 2.0) + pow((points[0].get_Y() - points[1].get_Y()), 2.0));
double line2 = sqrt(pow((points[1].get_X() - points[2].get_X()), 2.0) + pow((points[1].get_Y() - points[2].get_Y()), 2.0));
double line3 = sqrt(pow((points[2].get_X() - points[3].get_X()), 2.0) + pow((points[2].get_Y() - points[3].get_Y()), 2.0));
double line4 = sqrt(pow((points[3].get_X() - points[0].get_X()), 2.0) + pow((points[3].get_Y() - points[0].get_Y()), 2.0));
double diagonal = sqrt(pow((points[0].get_X() - points[2].get_X()), 2.0) + pow((points[0].get_Y() - points[2].get_Y()), 2.0));

double halfPerimeter = (line1 + line2 + diagonal) / 2.0;
area += sqrt(halfPerimeter * (halfPerimeter - line1) * (halfPerimeter - line2) * (halfPerimeter - diagonal));

halfPerimeter = (line3 + line4 + diagonal) / 2.0;
area += sqrt(halfPerimeter * (halfPerimeter - line3) * (halfPerimeter - line4) * (halfPerimeter - diagonal));

return area;
}
};

// 定义抽象工厂类
class AbstractGeometryFactory
{
protected:
Geometry* geometry;
public:
virtual Geometry* createGeometry(const vector<Point>& points) = 0;
virtual ~AbstractGeometryFactory(){}
};

// 定义具体的工厂类:三角形工厂,用于创建三角形
class TriangleFactory : public AbstractGeometryFactory
{
public:
TriangleFactory()
{
geometry = NULL;
}

Geometry* createGeometry(const vector<Point>& points)
{
if(points.size() != 3)
{
cout << "It's not a triangle" << endl;
}

geometry = new Triangle(points[0], points[1], points[2]);
return geometry;
}

~TriangleFactory()
{
if(geometry != NULL)
{
delete geometry;
geometry = NULL;
}
}
};

// 定义具体的工厂类:四边形工厂,用于创建四边形
class QuadrangleFactory : public AbstractGeometryFactory
{
public:
Geometry* createGeometry(const vector<Point>& points)
{
if(points.size() != 4)
{
cout << "It's not a Quadrangle" << endl;
}

geometry = new Quadrangle(points[0], points[1], points[2], points[3]);
return geometry;
}

~QuadrangleFactory()
{
if(geometry != NULL)
{
delete geometry;
geometry = NULL;
}
}
};

// 程序入口:用于测试上面的代码
int main(int argc, char** argv)
{
AbstractGeometryFactory* agf1;
AbstractGeometryFactory* agf2;

vector<Point> trianglePoints;
vector<Point> quadranglePoints;

Point a(0.0, 0.0);
Point b(6.0, 0.0);
Point c(6.0, 6.0);
Point d(0.0, 6.0);

trianglePoints.push_back(a);
trianglePoints.push_back(b);
trianglePoints.push_back(c);

quadranglePoints.push_back(a);
quadranglePoints.push_back(b);
quadranglePoints.push_back(c);
quadranglePoints.push_back(d);

agf1 = new TriangleFactory;
agf2 = new QuadrangleFactory;

double triangleArea = (agf1->createGeometry(trianglePoints))->calculateArea();
cout << "The area of the triangle is:\t" << triangleArea << endl;

double quadrangleArea = (agf2->createGeometry(quadranglePoints))->calculateArea();
cout << "The area of the quadrangle is:\t" << quadrangleArea << endl;

delete agf1;
delete agf2;

return 0;
}


另外,如果楼主对这个模式感兴趣,可以参考拙作:
C++实现Factory Method模式
j8daxue 2012-05-24
  • 打赏
  • 举报
回复
竟然用拼音命名...
看看loki的工厂模式吧。
nature19862001 2012-05-24
  • 打赏
  • 举报
回复
告诉你一个通用的指针转换方法,强制转换,天下无敌。。
baichi4141 2012-05-24
  • 打赏
  • 举报
回复
基类“图形”少了一个public
能看懂就行
W170532934 2012-05-24
  • 打赏
  • 举报
回复
把你的每个类都需要实现的函数抽象出来,放在基类里面,作为虚函数。然后每个类都继承这个类,依次实现这些函数。具体的可以去看下设计模式的工程模式
baichi4141 2012-05-24
  • 打赏
  • 举报
回复
class 图形
{
virtual double area( void ) = 0;
}
class 三角形 : public 图形
{
public:
三角形( p1, p2, p3 );//构造函数
virtual double area( void ) { };
};
class 四边形 : public 图形
{
public:
四边形( p1, p2, p3, p4 );//构造函数
virtual double area( void ) { };
};
class 五边形 : public 图形
{
public:
五边形( p1, p2, p3, p4, p5 );//构造函数
virtual double area( void ) { };
};

图形 * A = NULL;
if( 输入为三角形 )
A = new 三角形( p1, p2, p3 )
if( 输入为四边形 )
A = new 四边形( p1, p2, p3, p4 )
if( 输入为五边形 )
A = new 五边形( p1, p2, p3, p4, p5 )

A->area();
j8daxue 2012-05-24
  • 打赏
  • 举报
回复
类设计不合理,竟然用拼音表示类名。

类型ID + MAP + Creater = 工厂
给你的每个类别定义ID
用map关联此ID到一个生成器
由工厂来建立对象,赋值给基类指针。
silent_missile 2012-05-24
  • 打赏
  • 举报
回复
别批评我了,我承认错误。

这个基类要怎么设计呢,代码我写起来倒是不费事。就算是派生出来“三角形”“四边形”“五边形”,接下来的统一接口又该怎么实现呢?
baichi4141 2012-05-24
  • 打赏
  • 举报
回复
继承的关系是is a
五边形是四边形的一种吗?四边形是三角形的一种吗?明明不是is a的关系,你非要使用继承,自然撞得满头包

定义一个基类“图形”,由它派生出“三角形”“四边形”“五边形”
silent_missile 2012-05-24
  • 打赏
  • 举报
回复
我很菜的,工厂模式之类的也不是很懂
W170532934 2012-05-24
  • 打赏
  • 举报
回复
我觉得你的继承关系好像乱了。四边形是三角形吗?好像不是哎。你可以抽象个基础类出来。然后用那个设计模式里面的工厂模式来试试。
silent_missile 2012-05-24
  • 打赏
  • 举报
回复
哇,10楼的指点好全面,等我先用6楼的方法把这个活交上去,闲下来了一定按照10楼的工厂模式重新做。
silent_missile 2012-05-24
  • 打赏
  • 举报
回复
谢谢,6楼的方法已经解决了我的问题

更进一步的,如果除了一次判断以外,还需要类型转换的话,可以使用先delete再new的方法,dynamic_cast实践检验不太好使。

64,662

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧