Как правильно реализовать производные классы с произвольными комбинациями распространенных реализаций виртуальных функций? - PullRequest
0 голосов
/ 30 октября 2018

Как правильно реализовать набор производных классов с различными комбинациями реализаций функций-членов без копирования кода? Классы W, X, Y и Z все являются производными от класса base, поскольку они должны иметь возможность доступа к переменным-членам базового класса.

Я знаю способ сделать это с наследованием алмазов, но я подозреваю, что есть лучший способ.

class base {
      virtual void f() { /* implementation f_0 */ }
      virtual void g() { /* implementation g_0 */ }
      virtual void h() { /* implementation h_0 */ }
  };

 class W : public base {
      void g() override { /* implementation g_1 */ }
  };

  class X : public base {
      void g() override { /* implementation g_1 */ }
      void h() override { /* implementation h_1 */ }
  };

  class Y : public base {
      void f() override { /* implementation f_1 */ }
      void h() override { /* implementation h_1 */ }
  };

  class Z : public base {
      void f() override { /* implementation f_1 */ }
      void h() override { /* implementation h_2 */ }
  };

Ответы [ 2 ]

0 голосов
/ 15 марта 2019

Марк Грегуар обсуждает эту тему в главе 10 Professional C ++ .

Вот способ сделать это с наследованием алмазов.

  #include <iostream>
  using namespace std;

  struct base {
      virtual void f() { cout << "f_0\n"; /* implementation f_0 */ }
      virtual void g() { cout << "g_0\n"; /* implementation g_0 */ }
      virtual void h() { cout << "h_0\n"; /* implementation h_0 */ }
  };

  struct f_1 : public virtual base {
      void f() override { cout << "f_1\n"; /* implementation f_1 */ }
  };

  struct g_1 : public virtual base {
      void g() override { cout << "g_1\n"; /* implementation g_1 */ }
  };

  struct h_1 : public virtual base {
      void h() override { cout << "h_1\n"; /* implementation h_1 */ }
  };

  struct h_2 : public virtual base {
      void h() override { cout << "h_2\n"; /* implementation h_2 */ }
  };


  struct W : public g_1  {
      // void g() override { /* implementation g_1 */ }
  };

  struct X : public g_1, h_1 {
      // void g() override { /* implementation g_1 */ }
      // void h() override { /* implementation h_1 */ }
  };

  struct Y : public f_1, h_1 {
      // void f() override { /* implementation f_1 */ }
      // void h() override { /* implementation h_1 */ }
  };

  struct Z : public f_1, h_2 {
      // void f() override { /* implementation f_1 */ }
      // void h() override { /* implementation h_2 */ }
  };

  int main() {

      cout << "\nW\n";
      W w;
      w.f();
      w.g();
      w.h();

      cout << "\nX\n";
      X x;
      x.f();
      x.g();
      x.h();

      cout << "\nY\n";
      Y y;
      y.f();
      y.g();
      y.h();

      cout << "\nZ\n";
      Z z;
      z.f();
      z.g();
      z.h();
  }

Выход:

W
f_0
g_1
h_0

X
f_0
g_1
h_1

Y
f_1
g_0
h_1

Z
f_1
g_0
h_2
0 голосов
/ 30 октября 2018

Использовать промежуточный класс с реализацией по умолчанию:

class base {
public:
    virtual ~base() = default;
    virtual void f() = 0;
    virtual void g() = 0;
    virtual void h() = 0;
};

class derived : public base {
    void f() override { /* implementation f_0 */ }
    void g() override { /* implementation g_0 */ }
    void h() override { /* implementation h_0 */ }
};


class X : public derived {
    void g() override { /* implementation g_1 */ }
};

class Y : public derived {
    void f() override { /* implementation f_1 */ }
};

class Z : public derived {
    void h() override { /* implementation h_1 */ }
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...