views:

169

answers:

9

I know there are solved questions related to this issue, but I still can't figure out how to resolve my problem.

I have something like this:

class Base
{
   static Base* createBase()
   {
      Base *b = new Base();
      ... //does a lot of weird things
      return b;
   }
}

class Child : public Base
{
   static Child* createChild()
   {
      Child *c = createBase(); // error
      return c;          
   }
}

I know why it doesn't work, but I have to find a way to do it. The createBase function does a lot of things so I don't want to recode it.

Any suggestions?

+1  A: 

You should be using

Child *c = new Child();

Otherwise you are trying to create a Base class instance and call it a Child.

RE your comment:

Perhaps you could change

static Base* createBase();

static void createBase(Base *b);

If you pass the instance into this method you could use it with both Child and Base

for example:

Base *b = new Base();
Base::createBase(b);

Child *c = new Child();
Base::createBase(c);

or alternatively

static Base *createBase(Base *b = NULL){
    if(b == NULL){
        b = new Base;
    }
    //do your stuff
    return b;

and for the child:

static Child* createChild(){
    Child *c = new Child;
    createBase(c);
    return c;

This way you can use both:

b = Base::createBase();
c = Child::createChild();
GWW
But I want to do all those weird stuff createBase does.... without copy/paste since its a very large method.
sara
Could that weird stuff be moved to the Base constructor instead of the static method?
GWW
Sorry, I should have mentioned that I can't modify the Base class.
sara
If you can't modify the Base class you may have to duplicate the behavior in that method then.
GWW
Yeah, I thought so. Thanks anyway!
sara
+1  A: 

Perhaps you should re-define createBase as follows:

template< class TheClass > static TheClass* create()
{
  TheClass *ret = new TheClass();
  ... //does a lot of weird things
  return ret;
}

You can then create an object as follows:

Child* pChild = create< Child >();

This may not be appropriate depending what the "weird" things are but its one possible way of solving your issues.

Goz
+9  A: 

Why do you expect that to work? You can't treat a Base object as if it were a Child object, because the Child class might have all sorts of additional data that Base does not.

In order to get the effect you're looking for, there are two ways to do it:

The first way, and probably the best idea, is to move the logic from createBase into the Base constructor. The Base constructor will run whether you're creating a Base or something derived from it. It looks like you're trying to do the work of initializing the base object, and that's exactly what constructors are for!

If for some reason this will not work in your case, the other option is to create a protected initialize method in Base which accepts a Base* and does all the work that you are currently doing in createBase, e.g.

class Base
{
  public:

   static Base* createBase()
   {
       Base* b = new Base();
       initialize(b);
       return b;
   }

  protected:

   static void initialize(Base* b)
   {
      ... //does a lot of weird things
   }
}

class Child : public Base
{
  public:
   static Child* createChild()
   {
      Child *c = new Child(); 
      initialize(c):
      return c;          
   }
}

Note that this works since, while you can't treat a Base* as if it were a Child*, you can go the other way and treat a Child* as if it were a Base*, because the Child class is guaranteed to have at least everything that the Base class does, due to the nature of inheritance.

Edit: I saw you post in a comment to another answer that you cannot modify the definition of Base. In that case, you are completely out of luck and you will have to accept the need to copy-and-paste, given the restrictions in play. You are not going to be able to call createBase and get back a pointer to an object of any type other than Base if you cannot modify its code.

Tyler McHenry
I'd argue you are better off making initialise a virtual member function rather than a static as this would allow you to add any "further" intialisation to the child class while still calling the base class function from the derived class function ... but other than that good answer :)
Goz
@Goz True, but for the same reason the code should be in the constructor in the first place.
Tyler McHenry
@Tyler: Fair point ;)
Goz
All he needs is to put things in a constructor. Nothing else is required.
Martin York
+1  A: 

Don't the "weird" things belong in the Base constructor. Then by constructing the Child your base gets properly constructed?

Otherwise just refactor the code into a method you call from both places - definately don't copy it.

djna
A: 

You can use constructors to do the work for you:

class Base
{
   Base()
   {
     // does a lot of weird things
   }

  static Base* createBase()
  {
     return new Base();
  }

};

class Child : public Base
{
   Child()
   {
      // Do child's weird things here        
   }

  static Child* createChild()
  {
     return new Child();
  }
};

Base *instance1 = new Child();  // Works as expected
Base *instance2 = Child::createChild();  // Works as expected
Base *instance3 = new Base();  // Works as expected
Base *instance4 = Base::createBase();  // Works as expected

EDIT:
If you can't modify the Base class, you shouldn't derive from it this way. The class is apparently meant to have its own functionality and the static construction method suggests some more complex usage. You might want to use the Decorator design pattern instead of inheritance in this case: http://en.wikipedia.org/wiki/Decorator_pattern

dark_charlie
A: 

how about this

class Base
{
public:
   static Base* createBase()
   {
      Base *b = new Base();
      //does a lot of weird things
      return b;
   }
};

class Child
{
   protected:
   Base* m_basePtr;

public:
   operator Base&(){return *m_basePtr;}
   static Child* createChild()
   {
      Child *c=new Child;
      c->m_basePtr=Base::createBase();
      return c;          
   }
};

but you have to delete the pointer at the destructor

frag
A: 

What you want to do is:

class Base
{
  Base()
  {
         ... //does a lot of weird things
  }
};

class Child : public Base
{
  Child Child() // This calls the base constructor auto-magically
  {
  }
}

int main()
{
    Child  childOne;
    Base   baseOne;

    Child*  childPtr = new Child();
    Base*   basePtr1 = new Child();
    Base*   basePtr2 = new Base();
}
Martin York
A: 

If you really need to do this, try to cast it

class Base
{
public:
   static Base* createBase()
   {
      Base *b = new Base();
      //does a lot of weird things
      return b;
   }
};

class Child : public Base
{
public:
   static Child* createChild()
   {
      Child *c = (Child*)createBase(); // will compile
      return c;          
   }
};
OleDid
+1  A: 

overloading new for Base class might solve your issue.

class UTIL{

static size_t size;

public: static void setSize(size_t t) { //mutex protection size = t; }

static size_t getsize(); // should only be called from inside new of class A

};

class A { int i;

public: static A* createA() {

    A* a = new A();
    a->i = 10;
    return a;
}

void* operator new (size_t size) throw (const char *){

void * p = malloc(UTIL::getsize());

if (p == 0) throw "allocation failure";

return p;

}

void operator delete (void *p){

free(p); }

};

size_t UTIL::size = sizeof(A);

size_t UTIL::getsize() {

    //mutex protection
    size_t tmp = size;
    size = sizeof(A);
    return tmp;

}

class B {

public: int j; static B* createB() {

           //take mutex

    UTIL::setSize(sizeof(B));
    B* b = (B*)(A::createA());
    b->j = 20;
    //release Mutex
    return b;
}

};

bala sreekanth