C ++ разрешение перегрузки - PullRequest
7 голосов
/ 11 июня 2011

Я хочу использовать наследование, чтобы объект обрабатывался по-разному, в зависимости от того, где в иерархии он падает

( аналогично этому вопросу 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 ) ;
};

. Вы храните массив различных типов Shape * иcall

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

Но вы получаете ошибку компилятора

ошибка C2664: «Пересечение 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 ) ;

Можете ли вы сделать это первым способом, который я показал или НИКОГДА?

Ответы [ 3 ]

4 голосов
/ 11 июня 2011

Нет, вы не можете сделать это первым способом.Разрешение перегрузки в C ++ основано на статических типах аргументов функции.Это решается во время компиляции.В вашем примере статический тип - Shape *, и в вашем классе нет функции, которая бы принимала Shape * (отсюда и ошибка).Компилятору не важно, что ваш указатель может указывать на Sphere во время выполнения.

Чтобы реализовать то, что вы пытаетесь реализовать, вы должны «направить» ваши вызовы через средство, которое использует динамические типы объектов, то есть через вызовы виртуальных функций, что вамсделать в вашем втором примере.

Ваш второй пример немного упрощен, поскольку тип одного из задействованных объектов известен во время компиляции (Ray).В более сложном случае оба объекта, участвующие в «пересечении», могут быть динамического типа.Если вы хотите обработать что-то подобное, вы можете использовать так называемую технику «двойной отправки» (найдите ее).

4 голосов
/ 11 июня 2011

Вы должны сделать это наоборот.Разрешение перегрузки происходит во время компиляции, когда тип того, с чем вы его вызываете - Shape*.

0 голосов
/ 11 июня 2011

Может быть Вы можете получить это с информацией 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
    }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...