2015-04-07 1 views
2

У меня есть что-то вроде этого:C++ называют в срезах метод базового класса объекта

#include <iostream> 

class X; 

class A { 
public: 
    virtual void bar(X &x); 
}; 

class B : public A { 
public: 
}; 

class X { 
public: 
    void foo(A &a) { std::cout << "foo A" << std::endl; } 
    void foo(B &b) { std::cout << "foo B" << std::endl; } 
}; 

void A::bar(X &x) { x.foo(*this); } 

int main(int argc, char **argv) { 
    X x; 
    B b; 
    b.bar(x); 
    return 0; 
} 

скомпилировать его и выполнить его, вы будете иметь:

# ./a.out 
foo A 
# 

Я считаю, что это происходит потому, что объект нарезана когда приведение к А. Как я могу избежать этого, так что я получить

foo B 

без применения способа в B или использовать некоторые странности вроде Curiously recurring template pattern?

ответ

5

Здесь нет нарезки, потому что вы тщательно передаете объекты по ссылке; Нарезка требует манипулирования объектом по значению.

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

void A::bar(X &x) { 
    x.foo(*this); 
} 

он должен решить, во время компиляции, какой из двух перегрузок выбрать. Решение прост: компилятор знает, что *this имеет тип A, поэтому он вызывает функцию void foo(A &a).

Вы не можете заставить его работать без реализации того же метода в B*, используя шаблоны, или реализации вашей собственной схемы доставки с объектами функции или лямбды.

* в этом случае вы в конечном итоге с почти классической C++ реализации в Visitor Pattern, методики реализации Double Dispatch.

+0

Хорошо, ваш ответ правильный, но, как бы то ни было, моя проблема не была правильно смоделирована в моем вопросе. См. Http://stackoverflow.com/questions/29490493/c-function-overload-with-parent-and-child. –