C ++ Design (поведение в базовом классе, закрытый член предоставляется в производном классе) - PullRequest
0 голосов
/ 11 октября 2011

У меня есть 6 классов, которые выполняют одинаковые действия. Я хотел бы перенести обычное поведение в общий [базовый] класс.

Есть действия, которые нужно выполнить на 6 отдельных объектах. Шесть объектов расположены в производных классах. Интуитивно понятно, что к закрытым объектам-членам можно получить доступ через дочерний (производный класс) базового класса.

Что такое шаблон C ++, который я ищу?

class Base
{
  // Common behavior, operate on m_object
  ...
  void Foo()
  {
    m_object.Bar();
  }
};

class Derived1 : public Base
{
  // No methods, use Base methods

  private:
  MyObject1 m_object;
}

class Derived2 : public Base
{
  // No methods, use Base methods

  private:
  MyObject2 m_object;
}

В эту ситуацию меня загоняет: MyObject1, MyObject2 и т. Д. Предлагают Bar(), но не разделяют общий базовый класс. Я действительно не могу исправить вывод, потому что объекты приходят из внешней библиотеки.

Ответы [ 5 ]

5 голосов
/ 11 октября 2011

Если они введены в производные классы, то базовый класс не сможет напрямую получить к ним доступ. Как базовый класс узнает, что у всех производных классов есть определенный член?

Вы можете использовать виртуальные защищенные методы, например, так:

class my_base
{
protected:
    virtual int get_whatever();
    virtual double get_whatever2();
private:
    void process()
    {
       int y = get_whatever();
       double x = get_whatever2();
       //yay, profit?
    }
}

class my_derived_1 : my_base
{
protected:
    virtual int get_whatever()
    {
        return _my_integer;
    }

    virtual double get_whatever2()
    {
       return _my_double;
    }
}

Другая возможность (если вы хотите вызывать базовые методы из производных классов) - просто предоставить аргументы базовым методам.

class my_base
{
protected:
    void handle_whatever(int & arg);
};

class my_derived : my_base
{
    void do()
    {
      my_base::handle_whatever(member);
    }

    int member;
};
1 голос
/ 11 октября 2011

Рассматривали ли вы использование наследства?

class FooBar
{
   MyObject m_object;
public:
   FooBar(MyObject m): m_object(m) {}
   //operate on different m_objects all you want
};
1 голос
/ 11 октября 2011

C ++ делает и не делает. Он имеет очень мощную поддержку множественного наследования, поэтому ключевое слово super отсутствует. Зачем? Представьте, что ваш базовый класс, скажем, наследуется еще двумя классами или даже является частью виртуальной иерархии наследования. В этом случае вы не можете точно сказать, что должно означать super. С другой стороны, существуют виртуальные методы, вы всегда можете иметь их в базовом классе и реализовать в производных классах (это то, что делают языки, подобные Java, за исключением того, что они не поддерживают множественное наследование классов). Если вы не хотите идти с полиморфизмом, вы можете использовать что-то вроде этого:

#include <cstdio>

template <typename T>
struct Base
{
    void foo ()
    {
        std::printf ("Base::foo\n");
        static_cast<T *> (this)->bar ();
    }
};

struct Derived : Base<Derived>
{
    void bar ()
    {
        std::printf ("Derived::bar\n");
    }
};

int
main ()
{
    Derived d;
    d.foo ();
}

Это очень простой пример - вы можете дополнить приведенный выше пример контролем доступа, друзьями, утверждениями времени компиляции и так далее, но вы поняли идею.

0 голосов
/ 11 октября 2011

А как насчет получения ваших шести отдельных объектов из общего базового класса? Затем вы можете объявить виртуальные методы в этом базовом классе, чтобы создать интерфейс, а затем реализовать их в классах производных объектов.

0 голосов
/ 11 октября 2011

Может быть, вам просто нужен шаблон вместо суперкласса и 6 производных классов?

Кажется, вам нужно получить доступ не к родительскому полю, а к дочернему полю. Вы должны сделать это, введя абстрактный метод:

class ParentClass
{
  public:
    void f();
  protected:
    virtual int getSomething() = 0;
};

ParentClass::f()
{
    cout << getSomething() << endl;
}

class DerivedClass : public ParentClass
{
  protected:
    virtual int getSomething();
}

DerivedClass::getSomething() { return 42; }

Если вам нужен доступ к методу родителя, просто используйте ParentClass::method(...):

class ParentClass
{
  public:
    virtual void f();
};

class DerivedClass : public ParentClass
{
  public:
    virtual void f();
};

void DerivedClass::f()
{
    ParentClass::f();
}
...