Функции виртуального переопределения С++ с одинаковым именем
У меня есть что-то подобное (упрощенное)
class A
{
public:
virtual void Function () = 0;
};
class B
{
public:
virtual void Function () = 0;
};
class Impl : public A , public B
{
public:
????
};
Как я могу реализовать функцию() для A и функцию() для B?
Visual С++ позволяет вам определять конкретную встроенную функцию (т.е. Не в файле cpp),
но я предполагаю, что это расширение. GCC жалуется на это.
Есть ли стандартный С++ способ сообщить компилятору, какую функцию я хочу переопределить?
(visual С++ 2008)
class Impl : public A , public B
{
public:
void A::Function () { cout << "A::Function" << endl; }
void B::Function () { cout << "B::Function" << endl; }
};
Спасибо!
Ответы
Ответ 1
Вы не можете использовать там квалифицированные имена. Я пишу void Function() { ... }
, вы переопределяете обе функции. Херб Саттер показывает как это можно решить.
Другой вариант - переименовать эти функции, потому что, видимо, они делают что-то другое (в противном случае я не вижу проблемы переопределения как с одинаковым поведением).
Ответ 2
Как обходной путь, попробуйте
struct Impl_A : A
{
void Function () { cout << "A::Function" << endl; }
};
struct Impl_B : B
{
void Function () { cout << "B::function" << endl; }
};
struct Impl : Impl_A, Impl_B {};
Ответ 3
Я могу предложить другой способ решить эту проблему. Вы можете добавить wrapper Typed
, который изменяет подпись Function
, добавляя параметр фиктивного файла. Таким образом, вы можете различать методы в своей реализации.
class A {
public:
virtual void Function() = 0;
virtual ~A() = default;
};
class B {
public:
virtual void Function() = 0;
virtual ~B() = default;
};
template<typename T>
class Typed : public T {
public:
virtual void Function(T* dummy) = 0;
void Function() override {
Function(nullptr);
}
};
class Impl : public Typed<A>, public Typed<B> {
public:
void Function(A* dummy) override {
std::cerr << "implements A::Function()" << std::endl;
}
void Function(B* dummy) override {
std::cerr << "implements B::Function()" << std::endl;
}
};
Преимущество такого решения заключается в том, что вся реализация помещается в один класс.
Ответ 4
Если A и B являются интерфейсами, тогда я бы использовал виртуальный вывод для их объединения (чтобы они перекрывались). Если вам нужны разные реализации для Function
, если они вызваны с помощью указателя на A
или B
, я бы настоятельно рекомендовал выбрать другой проект. В противном случае это повредит.
Impl
"происходит от" A
и B
означает Impl
"означает" A
и B
. Полагаю, вы это не имеете в виду.
Impl
"реализует интерфейс" A
и B
означает Impl
"ведет себя как" A
и B
. то тот же интерфейс должен означать одно и то же поведение.
В обоих случаях, имеющих различное поведение в соответствии с типом используемого указателя, будет "шизофреник" и, безусловно, избежать ситуации.