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