C++过载解决方案

C++ overload resolution

本文关键字:解决方案 C++      更新时间:2023-10-16

我想使用继承以不同的方式处理对象,这取决于它在层次结构中属于的位置

(类似于这个C#问题)

假设您构建了一个Shape对象的层次结构,如:

class Shape {} ;
class Sphere : public Shape {} ;
class Triangle : public Shape {} ; ...

然后,您为Ray类配备以下方法:

class Ray
{
    Intersection intersects( const Sphere * s ) ;
    Intersection intersects( const Triangle * t ) ;
};

您存储各种类型的各种形状*的数组,并调用

vector<Shape*> shapes ; ...
//foreach shape..
Intersection int = ray.intersects( shapes[ i ] )

但是你得到了编译错误

错误C2664:"Intersection Ray::intersects(const Sphere*)const":无法将参数1从"Shape*const"转换为"const Sphere*"

你做错了什么?

唯一的方法是还是其他方法,使用

class Shape
{
    virtual Intersection intersects( const Ray* ray )=0 ;
} ;

那么每个类覆盖相交?然后呼叫

//foreach shape..
Intersection int = shapes[i]->intersects( ray ) ;

你能按照我展示的第一种方式做吗?

你必须以另一种方式来做。重载解析发生在编译时,此时调用它的类型是Shape*

不,你不能用第一种方法。C++中的重载解析基于静态类型的函数参数。它在编译时解决。在您的示例中,静态类型是Shape *,并且您的类中没有接受Shape *的函数(因此出现错误)。编译器并不关心您的指针在运行时是否实际指向Sphere

要实现您试图实现的内容,您必须通过一个依赖动态类型对象的工具来"引导"您的调用,即通过虚拟函数调用,这就是您在第二个示例中所做的。

您的第二个示例有点简化,因为其中一个对象的类型在编译时(Ray)是已知的。在更复杂的情况下,"交集"中涉及的两个对象都可以是动态类型的。如果你想处理这样的事情,你可以使用所谓的"双重调度"技术(搜索它)。

可能是您可以使用RTTI信息获取此信息。我还没有做,但这可能。

class Ray
{
    Intersection intersects( const Sphere * s ) ;
    Intersection intersects( const Triangle * t ) ;
    Intersection intersects( const Shape * s ) {
       //act on RTTI info, or 
       //use dynamic_cast to other types and check if the result is NULL or not
    }
};
相关文章: