【问题标题】:C++ overload resolutionC++ 重载决议
【发布时间】:2011-06-11 16:00:42
【问题描述】:

我想使用继承来根据对象在层次结构中的位置以不同的方式处理对象

(similar to this C# question)

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

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

然后为 Ray 类配备如下方法:

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

您存储各种类型的各种 Shape* 数组并调用

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 ) ;

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

【问题讨论】:

标签: c++ inheritance


【解决方案1】:

你必须反过来做。重载解析发生在编译时,当你调用它的类型是Shape*。

【讨论】:

    【解决方案2】:

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

    要实现您要实现的功能,您必须通过依赖于对象的 动态 类型的工具“引导”您的调用,即通过虚函数调用,这就是您所做的你的第二个例子。

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

    【讨论】:

      【解决方案3】:

      可能您可以使用 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
          }
      };
      

      【讨论】:

      • 是的,我知道typeid(),但我当然想避免使用它
      • 那么答案几乎肯定是否定的。
      猜你喜欢
      • 1970-01-01
      • 2012-02-25
      • 2011-03-26
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 2014-04-20
      • 1970-01-01
      • 2011-05-08
      相关资源
      最近更新 更多