我有两个来自基类Triangle
的派生类Sphere
和Shape
。
我遇到的情况是我在类Shape*
中存储了一个基类指针A
,并为每个派生类型A
提供了两个类doSomething(Sphere* sp)
的重载成员函数}和doSomething(Triangle* tr)
。
class Shape
{
public:
Shape() {};
virtual ~Shape() = 0;
};
class Triangle : public Shape
{
public:
Triangle();
};
class Sphere : public Shape
{
public:
Sphere();
};
class A
{
private:
Shape* shape;
void doSomething(Triangle* tr);
void doSomething(Sphere* sp);
public:
A();
~A();
};
但是,当我尝试通过将Shape*
类型的指针传递到doSomething
函数来运行我的代码时,我收到以下错误:
candidate function not viable: cannot convert from base class pointer 'value_type'
(aka 'Shape *') to derived class pointer 'const Triangle *' for 1st argument
void A::doSomething(Triangle* tr) {
Sphere
的相同消息。我也确定虽然是Shape *
类型的指针,但它实际上指向了一个派生对象。
那么,如何在不修改Triangle
和Sphere
类且仅修改A
的情况下解决此问题?
答案 0 :(得分:3)
在C ++中无法做到这一点。进行动态调度的唯一方法是调用虚方法:
shape->doSomething();
Triangle::doSomething
和Sphere::doSomething
可能是虚拟Shape::doSomething
的不同实现。
因此,您需要更改代码结构,以便控制调用的shape
本身。或者......你可以拥有一个巨大的分支,你可以依次尝试每个分支:
void doSomething() {
if (Triangle* t = dynamic_cast<Triangle*>(shape)) {
doSomething(t);
}
else if (Sphere* s = dynamic_cast<Sphere*>(shape)) {
doSomething(s);
}
// etc.
}
我建议不要这样做。除了可怕的阅读之外,它也很慢而且不可维护。
答案 1 :(得分:2)
您需要使用dynamic_cast
找出Shape*
所指向的派生类并获取指向该类的指针,然后您可以将该指针传递给doSomething()
重载。需要,例如:
class A
{
private:
Shape* shape;
void doSomething(Shape* sh);
void doSomething(Triangle* tr);
void doSomething(Sphere* sp);
public:
A();
~A();
};
void A::doSomething(Shape* sh)
{
if (Sphere *sp = dynamic_cast<Sphere*>(sh))
doSomething(sp);
else if (Triangle *tr = dynamic_cast<Triangle*>(sh))
doSomething(tr);
}
答案 2 :(得分:-1)
必须有一些决策过程才能在球体或三角形之间进行选择。
如果您在编译时确定了所需的形状,则可以保留您的设计,并使用部分模板专业化。 (此示例已使用g ++ 4.7.2编译)
#include <iostream>
using std::cout;
using std::endl;
struct Shape
{
};
struct Sphere : Shape
{
double radius;
Sphere(double radius): radius(radius) {}
};
struct Triangle : Shape
{
double a, b, c;
Triangle(double a, double b, double c): a(a), b(b), c(c) {}
};
void foo(Sphere * b)
{
cout << "Sphere " << b->radius << endl;
};
void foo(Triangle * c)
{
cout << "Triangle " << c->a << ',' << c->b << ',' << c->c << endl;
};
template<bool>
struct ShapeShifter
{
};
template<>
struct ShapeShifter<true>
{
typedef Sphere* Type;
};
template<>
struct ShapeShifter<false>
{
typedef Triangle* Type;
};
int main()
{
Shape * a1 = new Sphere(1.5);
Shape * a2 = new Triangle(3,4,5);
const int x = 0;
foo(static_cast<ShapeShifter<x == 0>::Type>(a1));
foo(static_cast<ShapeShifter<x != 0>::Type>(a2));
}
否则你可以指出使用dynamic_cast
。