Подтвердить что ты не робот

Функции виртуального переопределения С++ с одинаковым именем

У меня есть что-то подобное (упрощенное)

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; }
};

Спасибо!

4b9b3361

Ответ 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. то тот же интерфейс должен означать одно и то же поведение.

В обоих случаях, имеющих различное поведение в соответствии с типом используемого указателя, будет "шизофреник" и, безусловно, избежать ситуации.