C ++ виртуальные функции переопределения с тем же именем - PullRequest
19 голосов
/ 30 июня 2010

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

class A
{
  public:
    virtual void Function () = 0;
};

class B
{
  public:
    virtual void Function () = 0;
};

class Impl : public A , public B
{
  public:
        ????
};

Как я могу реализовать функцию () для A и функцию () для B? Visual C ++ позволяет вам определять только определенную встроенную функцию (т.е. не в файле cpp), но я полагаю, это расширение. GCC жалуется на это. Есть ли в C ++ стандартный способ сообщить компилятору, какую функцию я хочу переопределить?

(Visual C ++ 2008)

class Impl : public A , public B
{
  public:
     void A::Function () {  cout << "A::Function" << endl; }
     void B::Function () {  cout << "B::Function" << endl; }
};

Спасибо!

Ответы [ 4 ]

31 голосов
/ 30 июня 2010

Вы не можете использовать квалифицированные имена там.Если вы пишете void Function() { ... }, вы переопределяете обе функции.Трава Саттер показывает , как ее можно решить .

Другой вариант - переименовать эти функции, потому что, по-видимому, они делают что-то другое (в противном случае я не вижу проблемы переопределения обоих с одинаковым поведением).

2 голосов
/ 29 октября 2013

Я могу предложить другой способ решения этой проблемы.Вы можете добавить оболочку 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;
  }
};

Преимущество такого решения состоит в том, что все реализации размещаются в одном классе.

2 голосов
/ 30 июня 2010

В качестве обходного пути попробуйте

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 {};
0 голосов
/ 30 июня 2010

Если A и B являются интерфейсами, то я бы использовал виртуальный вывод, чтобы «соединить» их (сделать так, чтобы они перекрывались). Если вам нужны другие реализации для Function, если он вызывается через указатель на A или B, тогда я настоятельно рекомендую выбрать другой дизайн. В противном случае будет больно.

Impl "происходит от" A и B означает, что Impl "является" A и B. Я полагаю, вы не имеете в виду это.

Impl «реализует интерфейс» A, а B означает, что Impl «ведет себя как» A и B. тогда тот же интерфейс должен означать то же поведение.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...