Visual Studio 2013.
Дано:
class base_1
{
public:
virtual void foo(int) = 0;
};
class base_2
{
public:
virtual void foo(int, double) = 0;
};
class join_1_2 : public virtual base_1, public virtual base_2
{};
У меня есть раковина:
void sink(join_1_2 ¶m)
{
param.foo(42, 3.14);
}
Но я получаю следующие ошибки компилятора:
ошибка C2385: неоднозначный доступ к ‘foo’
может быть ‘foo’ в базе ‘base_1’
или может быть ‘foo’ в базе ‘base_2’
ошибка C2660: «base_1 :: foo»: функция не принимает 2 аргумента
ошибка C3861: ‘foo’: идентификатор не найден
Я знаю, что могу решить эту проблему с помощью:
param.base_2::foo(42, 3.14);
Но, как вы можете себе представить, виртуальное наследование — это уже один грех, с которым мне приходится жить. Я, вероятно, собираюсь написать адаптер. Но я не понимаю, что мешает компилятору решить foo в base_2. Мой коллега считает, что это ошибка компилятора, но я не так быстро винить вендора.
Что спецификация C ++ говорит о разрешении перегруженных виртуальных методов в базовых классах?
Это действительно двусмысленность в соответствии со стандартом, но вы можете использовать using
или укажите базовый класс явно:
class join_1_2 : public virtual base_1, public virtual base_2
{
public:
using base_1::foo;
using base_2::foo;
};
void sink(join_1_2 ¶m)
{
param.base_2::foo(42, 3.14);
}
7.3.3 Объявление об использовании
В целях разрешения перегрузки функции, которые вводятся объявлением использования в
Производный класс будет обрабатываться так, как если бы он был членом производного класса.
Эмпирическое правило заключается в том, что функции в разных областях не перегружаются — здесь наши foo
С в разных сферах. Если вы хотите, чтобы они перегрузились, вы захотите ввести их с используя декларирование:
class join_1_2 : public virtual base_1, public virtual base_2
{
public:
using base_1::foo;
using base_2::foo;
};