C++ C++;指向指针的指针不支持多态性

C++ C++;指向指针的指针不支持多态性,c++,pointers,polymorphism,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: Chi

我正在寻找一种合适的方法来清理指针。 下面是示例代码:

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**)’

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

与您的示例相近的是:

template <typename T>
RemoveObj(T **p)
{
    if (p == NULL) return;
    delete *p;
    *p = NULL;
}
模板
移除对象(T**p)
{
如果(p==NULL)返回;
删除*p;
*p=零;
}
此外,您可能希望改用std::auto_ptr。它看起来像:

int main()
{
   std::auto_ptr<Parent*> pPObj(new Parent);
   std::auto_ptr<Child*> pCObj(new Child);
   // no deletes needed anymore
intmain()
{
std::auto_ptr pPObj(新父级);
std::auto_ptr pCObj(新生儿);
//不再需要删除

<代码> > p>您可以从书项目8找到有用的信息。指针指向指针。

不需要包装删除,保持简单:

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
)删除数组类型的对象时会遇到问题。另一种方法当然是传递一个标志来表示您希望
delete[]
。但正如我所说的:KISS。

简单地说:

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

但是

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


“Child”和“Child*”不是相同的类型。

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


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

您需要做的是将指向刚删除的对象的所有指针置零。指针的概念是,将有多个指针存储同一对象的地址。如果没有,则没有理由使用裸指针,并且因此,您试图捕获的模式不是很有用,但您远不是第一个尝试这种模式的人。正如其他答案所提到的,处理指针的唯一方法是小心地控制对指针的访问

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

void Foo(Parent **pp)
{
    *pp = new OtherChild();
}
您的
子类
派生自
父类
,我的
其他子类
派生自父类。假设编译器允许您这样做:

Child *c = 0;
Foo(&c);
您希望它能工作,但如果它能工作,那么我们现在将有一个
指针
c
,它实际上指向
其他子
的实例。谁说这两种类型是兼容的


同样,这是一个非常常见的误解-它在其他语言中反复出现,特别是关于C#中的
List
List

可能是我发现的最简单的解决方案:

#define __REMOVE_OBJ(pObj) RemoveObj(pObj); pObj = NULL;
就叫这个:

   __REMOVE_OBJ(pPObj);
   __REMOVE_OBJ(pCObj);
但我自己也不太喜欢…

从讨论开始

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

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

关于第一个解决方案:与第一个建议编译并起作用的void RemoveObj(void**ppObj)相比,有何改进。void RemoveObj(void**ppObj)可以定义,但如果您尝试调用它,您的调用应该不会编译。@TOANE:我认为删除void*实际上是未定义的。使用模板解决方案,您有一个正确的静态类型。应该为void*调用什么非平凡的析构函数?删除“void*”是未定义的。我认为动态转换或重新解释转换也不会很坏?只有reall当我想调用*p->PubFunc()时需要y;Thx很多,解释得很好!!没问题!记住-没有什么比追加投票更能表达“谢谢”。也许我的示例太简单了…我也想在该函数中调用PubFunc()。。。