指针指针不支持C ++多态

时间:2009-04-10 07:39:46

标签: c++ pointers polymorphism

我正在寻找一种清洁指针的正确方法。 这里是示例代码:

class Parent {
   protected:
      int m_Var;
   public:
      Parent() : m_Var(0) {}
      virtual ~Parent() {}
      void PubFunc();
};

class Child : public Parent {
   protected:
      bool m_Bool;
   public:
      Child() : m_Bool(false) {}
      virtual ~Child() {}
      void ChildFunc();
};

void RemoveObj(Parent **ppObj)
{
   *ppObj->PubFunc();
   delete *ppObj;
   ppObj = NULL;
}

int main()
{
   Parent* pPObj = NULL;
   Child*  pCObj = NULL;
   pPObj = new Parent();
   pCObj = new Child();

   RemoveObj(&pPObj);
   RemoveObj(&pCObj); // This is line 33
   return 1;
}

但是编译器给出了错误:

classes.cpp:33: error: invalid conversion from ‘Child**’ to ‘Parent**’
classes.cpp:33: error:   initializing argument 1 of ‘void RemoveObj(Parent**)’

8 个答案:

答案 0 :(得分:12)

有很多方法可以正确处理内存。

接近你的例子的是:

template <typename T>
RemoveObj(T **p)
{
    if (p == NULL) return;
    delete *p;
    *p = NULL;
}

此外,您可能希望使用std :: auto_ptr。它看起来像是:

int main()
{
   std::auto_ptr<Parent*> pPObj(new Parent);
   std::auto_ptr<Child*> pCObj(new Child);
   // no deletes needed anymore

答案 1 :(得分:3)

说实话:

Child是Parent的子类,这意味着Child *可以替换为Parent *

BUT

Child *不是Parent *的子类,因此意味着Child **不能替换为Parent **

“儿童”和“儿童*”的类型不同。

答案 2 :(得分:3)

您需要做的是取消所有指向您刚刚删除的对象的指针。指针的想法是存在多个指针存储同一对象的地址。如果没有,没有理由使用裸指针,所以你试图捕获的模式不是很有用 - 但你远不是第一个尝试这个的人。正如其他答案所提到的,处理指针的唯一方法是仔细控制对它们的访问。

你的问题标题绝对正确!这是有充分理由的。指针标识存储特定类型的对象的位置。指向指针的指针使您能够更改指针指向的对象。

void Foo(Parent **pp)
{
    *pp = new OtherChild();
}

您的Child班级来自Parent,我的OtherChild班级也是如此。假设编译器允许您这样做:

Child *c = 0;
Foo(&c);

你希望它可以工作,但如果有,那么我们现在有一个Child指针c实际上指向OtherChild的实例。谁说这两种类型兼容?

同样,这是一个非常频繁的误解 - 它在这里反复出现其他语言,特别是关于C#中的List<Parent>List<Child>

答案 3 :(得分:2)

你不需要一个包装用于删除,保持简单:

int main()
{
  Parent* pPObj = NULL;
  Child*  pCObj = NULL;
  pPObj = new Parent();
  pCObj = new Child();

  delete pPObj;
  delete pCObj; // This is line 33
  return 1;
}

请记住,在使用RemoveObj删除数组类型对象时会遇到问题(因为您总是使用标量delete)。另一种选择当然是传递一个标志,表示你想要{​​{1}}。但正如我所说:亲吻。

答案 4 :(得分:2)

如果您的问题是处理内存和资源,最好的建议是完全忘记您的方法并使用智能指针。 std :: auto_ptr boost :: shared_ptr 将是一个起点。

如果使用智能指针保存所有堆分配的资源,则代码将更加健壮。

答案 5 :(得分:1)

你可以从书中找到一些有用的信息&lt; 项目8.指针的指针。

答案 6 :(得分:0)

可能是我找到的最简单的解决方案:

#define __REMOVE_OBJ(pObj) RemoveObj(pObj); pObj = NULL;

请拨打这个:

   __REMOVE_OBJ(pPObj);
   __REMOVE_OBJ(pCObj);

但我自己并不喜欢......

答案 7 :(得分:0)

关于make shared_ptr not use delete

的讨论

共享指针将确保您应该在需要时进行清理,并且不会访问被破坏的内容。此外,您可以专门化并提供替代销毁方法。

boost::shared_ptr<T> ptr( new T, std::mem_fun_ref(&T::deleteMe) );