如何将子类分配给基类?

时间:2010-09-21 16:07:26

标签: c++ class inheritance variable-assignment

我知道解决了与此问题相关的问题,但我仍然无法弄清楚如何解决我的问题。

我有这样的事情:

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

我知道为什么它不起作用,但我必须找到一种方法来做到这一点。 createBase函数做了很多事情,所以我不想重新编码它。

有什么建议吗?

8 个答案:

答案 0 :(得分:9)

为什么你希望这个工作?您不能将Base对象视为Child对象,因为Child类可能包含Base没有的所有其他数据。

为了获得您正在寻找的效果,有两种方法可以做到:

第一种方式,也许是最好的想法,是将逻辑从createBase移到Base构造函数中。无论您是创建Base还是从中派生的内容,Base构造函数都会运行。看起来你正在尝试初始化基础对象,而这正是构造函数的用途!

如果由于某些原因这不适用于您的情况,另一个选项是在initialize中创建受保护的Base方法,该方法接受Base*并完成您的所有工作目前正在createBase进行,例如

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

请注意,这是有效的,因为虽然您无法将Base*视为Child*,但您可以走另一条路并对待{{ 1}}就像它是Child*一样,因为Base*类由于继承的性质而至少保证Child类具有的所有内容。

编辑:我看到您在评论中发布了另一个答案,您无法修改Base的定义。在这种情况下,你完全没有运气,鉴于游戏中的限制,你必须接受复制和粘贴的需要。如果您无法修改其代码,则无法调用Base并返回指向createBase以外的任何类型对象的指针。

答案 1 :(得分:2)

为Base类重载new可能会解决您的问题。

类UTIL {

static size_t size;

公共:     static void setSize(size_t t)         {         //互斥保护         size = t;     }

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

};

A班 {     int i;

公共:     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)抛出“分配失败”;

返回p;

}

void operator delete(void * p){

自由(P); }

};

size_t UTIL :: size = sizeof(A);

size_t UTIL :: getsize() {

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

}

B级 {

公共:         int j;     static B * createB()     {

           //take mutex

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

};

答案 2 :(得分:1)

您应该使用

Child *c = new Child();

否则,您正在尝试创建Base类实例并将其称为Child。

重新评论:

也许你可以改变

static Base* createBase();

static void createBase(Base *b);

如果将实例传递给此方法,则可以将它与Child和Base一起使用

例如:

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

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

或者

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

和孩子:

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

这样你可以同时使用:

b = Base::createBase();
c = Child::createChild();

答案 3 :(得分:1)

也许您应该按如下方式重新定义createBase:

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

然后您可以按如下方式创建对象:

Child* pChild = create< Child >();

这可能不合适取决于“奇怪”的东西,但它是解决问题的一种可能方式。

答案 4 :(得分:1)

“构造函数”中是否存在“怪异”的东西。那么通过构建Child,您的基础是否正确构建了?

否则只需将代码重构为从两个地方调用的方法 - 肯定不要复制它。

答案 5 :(得分:0)

您可以使用构造函数为您完成工作:

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

修改
如果您无法修改Base类,则不应该以这种方式派生它。该类显然意味着具有自己的功能,静态构造方法建议使用更复杂的功能。在这种情况下,您可能希望使用Decorator设计模式而不是继承:http://en.wikipedia.org/wiki/Decorator_pattern

答案 6 :(得分:0)

这个怎么样

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

但你必须删除析构函数

的指针

答案 7 :(得分:0)

您想要做的是:

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