Без диспетчеризации virtual
перегруженное разрешение выполняется во время компиляции, то есть на основе статического типа объектов, а не динамического типа . Поскольку ab2
является std::shared_ptr<A>
, выбирается перегрузка A
.
Чтобы задействовать информацию типа времени выполнения (т. Е. Динамический тип объекта), необходимо использовать методы virtual
(иполиморфизм), а не разрешение перегрузки. Не ясно, как лучше всего включить это в данный пример.
Самый простой способ - предоставить A
виртуальный деструктор и некоторый виртуальный метод, такой как accept()
, который переопределяется в производных классах для отправки большинствусоответствующая перегрузка свободной функции явно. Однако есть и другие способы, это зависит от того, что вам нужно.
Следует также отметить, что в этом коде вообще нет SFINAE.
Повторять и отвечать на изменения: Если вы хотите использовать динамическую, а не статическую информацию о типе, ваш тип должен иметь хотя бы один виртуальный метод:
class A { virtual ~A(); };
Если вы это сделаете, то можете использовать, например, dynamic_cast
(или,поскольку вы используете std::shared_ptr
, std::dynamic_pointer_cast
) для определения типа объекта во время выполнения:
void accept(std::shared_ptr<B1> sp) { std::cout << "B1 "; }
void accept(std::shared_ptr<B2> sp) { std::cout << "B2 "; }
// How to ensure the overload call to right derived type ?
void accept(std::shared_ptr<A> sp) {
if (std::shared_ptr<B1> ptrB1 = std::dynamic_pointer_cast<B1>(sp))
accept(ptrB1);
else if (std::shared_ptr<B2> ptrB2 = std::dynamic_pointer_cast<B2>(sp))
accept(ptrB2);
else
// if is A, do another thing
}
Но если вы вручную dynamic_cast
между различными типами, как этоттогда у вас, вероятно, нет нужной абстракции. Посмотрите на варианты или шаблон посетителя (или спросите этот совет в новом вопросе, в котором вы подробно опишите проблему и имеющиеся у вас ограничения).