开发者

C++ Design (behavior in base class, private member supplied in derived class)

开发者 https://www.devze.com 2023-04-12 02:26 出处:网络
I have 6 classes which all perform the same actions. I would like to move common behavior to a common [base] class.

I have 6 classes which all perform the same actions. I would like to move common behavior to a common [base] class.

There are actions to b开发者_如何学Goe performed on 6 separate objects. The six objects are located in derived classes. Intuitively, the private member objects would be accessed through the child (derived class) in the base class.

What is the C++ pattern I am looking for?

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

The thing that is boxing me into this situation is MyObject1, MyObject2, etc offer Bar(), but don't share a common base class. I really can't fix the derivation because the objects come from an external library.


If they are introduced in the derived classes, then the base class cannot directly access them. How would the base class know that all derived classes have a specific member?

You could use virtual protected methods like so:

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

Another possibility (if you want to call the base methods from the derived classes) is to simply supply the arguments to the base methods.

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

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

    int member;
};


C++ does and doesn't. It has a very powerful multiple inheritance support, so there is no super keyword. Why? Imagine that your base class is, say, inherited by another two classes, or even is a part of virtual inheritance hierarchy. In that case you can't really tell what super is supposed to mean. On the other hand, there are virtual methods, you can always have them in base class and implement in derived classes (that's what languages like Java do, except that they they don't have multiple class inheritance support). If you don't want to go with polymorphism, you can use something like this:

#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 ();
}

This is an extremely simple example - you can extend the above example with access control, friends, compile-time assertions etcetera, but you get the idea.


Have you considered not using inheritance?

class FooBar
{
   MyObject m_object;
public:
   FooBar(MyObject m): m_object(m) {}
   //operate on different m_objects all you want
};


What about deriving your six separate objects from a common base class? Then you can declare virtual methods in that base class to create your interface, and then implement them in the derived object classes.


Maybe you just need a template instead of superclass and 6 derived classes?

It seems that you need to access not the parent's, but child's field. You should do it by introducing an abstract method:

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

If you need to access parent's method, just use ParentClass::method(...):

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

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

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号