user1065101
user1065101

Reputation:

returning instance of derived class from base class member function

Is it an O.K. design if i return an instance of Derived class from Base class member function(created using new Derived()) ?

Also this involves the need to forward declare the Derived class and also make the Derived class constructor public.

Code Sample :-

Class Base
{
 public:
  Base() {}
  Derived* get_new_derived(int X) 
  { 
    Derived *der = new Derived(X); 
    return der;  
  }
}

Class Derived : public Base
{
 private:
  int _X;
 protected:
  Derived(int X) { _X = X; }
 public:  
  Derived* get_new_derived(int X) 
  { 
    Derived *der = new Derived(X); 
    return der;  
  }
}

I have one more derived class(say Derived1). Now let's say :-

Usage1 :

Derived1* der1 = new Derived1();
Derived * der = der1->get_new_derived(10);

Usage2 :

Derived1* der1 = new Derived1();
Base* bs = der1;
Derived * der = bs->get_new_derived(10);

Upvotes: 4

Views: 2911

Answers (3)

gooddocteur
gooddocteur

Reputation: 109

How about this?

// The Curiously Recurring Template Pattern (CRTP)
template<class Derived>
class Base
{
  // methods within Base can use template to access members of Derived
};
class Derived : public Base<Derived>
{
  // ...
};

http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern

Upvotes: 2

In the general case, this usually indicates bad design - a base class shouldn't normally know/care about its derived classes.

Note that you can return a pointer to Derived typed as Base* - that's the principle of the Factory Method design pattern. Perhaps this fits your actual scenario?

Note however that all rules have exceptions. If your (base class + derived classes) represent a tighly coupled and coherent unit (such as a Tree interface with two subclasses FastTree and SmallTree, optimised for different purposes), it is acceptable for them to be aware of each other, and Tree defining such functions as:

std::unique_ptr<SmallTree> Tree::createSmallCopy() const
{
  return { new SmallTree(/*args*/) };
}

std::unique_ptr<FastTree> Tree::createFastCopy() const
{
  return { new FastTree(/*args*/) };
}

So it depends on your actual use case. I'd generally be wary of such design, it but it has its uses.


As a side note, in modern C++, you should never use an owning raw pointer - use a smart pointer like std::unique_ptr or boost::shared_ptr.

Upvotes: 3

egur
egur

Reputation: 7960

Yes you can do it. The question is whether you should.

You shouldn't do it since it implies Base knows Derived which isn't proper object oriented design. The dependencies should be one way - derived knows the Base and not vice versa.

Upvotes: 1

Related Questions