【问题标题】:How can I assign a child class to a base class?如何将子类分配给基类?
【发布时间】:2010-09-21 16:07:26
【问题描述】:

我知道有与此问题相关的已解决问题,但我仍然不知道如何解决我的问题。

我有这样的事情:

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 函数做了很多事情,所以我不想重新编码。

有什么建议吗?

【问题讨论】:

  • 好吧,为什么你必须想办法做到这一点?严重地。你知道你不能那样做,你为什么不能那样做。为什么你绝对必须有一个不指向ChildChild *
  • 另一个想法:Child 必须是Base 的孩子吗?它可以只包含Base 吗? (很可能不是,但你说得还不够让我知道。)
  • 如果将“奇怪的东西”移动到Base 构造函数中,那么createChild 可以只是return new Child

标签: c++ class inheritance variable-assignment


【解决方案1】:

您为什么希望它起作用?您不能将Base 对象视为Child 对象,因为Child 类可能包含Base 没有的各种附加数据。

为了得到你想要的效果,有两种方法:

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

如果由于某种原因这在您的情况下不起作用,另一种选择是在 Base 中创建一个受保护的 initialize 方法,该方法接受 Base* 并完成您当前在 @987654332 中所做的所有工作@,例如

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*,但您可以换一种方式将 Child* 视为是 Base*,因为由于继承的性质,Child 类保证至少具有 Base 类所做的一切。

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

【讨论】:

  • 我认为您最好将初始化一个虚拟成员函数而不是一个静态函数,因为这将允许您向子类添加任何“进一步”初始化,同时仍然调用基类函数派生类函数......但除了那个很好的答案:)
  • @Goz 是的,但出于同样的原因,代码首先应该在构造函数中。
  • 他所需要的只是将东西放入构造函数中。不需要其他任何东西。
【解决方案2】:

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

类 UTIL{

static size_t size;

公开: 静态无效 setSize(size_t t) { //互斥保护 大小 = t; }

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

};

A 级 { 诠释我;

公开: 静态 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 "分配失败";

返回 p;

}

void 运算符删除 (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 类 {

公开: 诠释 j; 静态 B* createB() {

           //take mutex

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

};

【讨论】:

    【解决方案3】:

    也许你应该重新定义 createBase 如下:

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

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

    Child* pChild = create< Child >();
    

    这可能不合适,具体取决于“奇怪”的事情是什么,但它是解决问题的一种可能方式。

    【讨论】:

      【解决方案4】:

      你应该使用

      Child *c = new Child();
      

      否则,您将尝试创建一个基类实例并将其称为子类。

      RE 你的评论:

      也许你可以改变

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

      【讨论】:

      • 但是我想做所有那些 createBase 做的奇怪的事情......没有复制/粘贴,因为它是一个非常大的方法。
      • 能不能把那些奇怪的东西移到 Base 构造函数而不是静态方法中?
      • 对不起,我应该提到我不能修改 Base 类。
      • 如果您无法修改 Base 类,您可能必须在该方法中复制行为。
      • 是的,我是这么认为的。还是谢谢!
      【解决方案5】:

      “奇怪”的东西不属于 Base 构造函数。然后通过构造 Child 来正确构造你的基础?

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

      【讨论】:

        【解决方案6】:

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

        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 类,则不应以这种方式派生它。该类显然意味着具有自己的功能,而静态构造方法建议使用一些更复杂的用法。在这种情况下,您可能希望使用装饰器设计模式而不是继承:http://en.wikipedia.org/wiki/Decorator_pattern

        【讨论】:

          【解决方案7】:

          这个怎么样

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

          但你必须删除析构函数处的指针

          【讨论】:

            【解决方案8】:

            你想做的是:

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

            【讨论】:

              猜你喜欢
              • 2011-04-14
              • 1970-01-01
              • 1970-01-01
              • 2011-10-20
              • 1970-01-01
              • 1970-01-01
              • 2015-06-08
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多