将子对象指针更改为父指针(无内存泄漏)
Changing child object pointer to parent pointer (without memory leak)
本题中:
我遇到这样一种情况,父指针指向由前面的条件语句确定的两个可能对象之一。这是代码:(重新发布解决方案)
ClassParent *parentPointer; //Declare pointer to parent
if (condition) {
ClassChild1* mychild = new mychild1(); //Initialize ClassChild1 object with pointer mychild
parentPointer = mychild;//Parent pointer points to child1
}
if (!condition) {
ClassChild2* mychild = new mychild2(); //Initialize ClassChild1 object with pointer mychild
parentPointer = mychild;//Parent pointer points to child2
}
cout << *parentPointer;
问题是,我的对象是用 mychild 指针创建的,但我希望这个指针是临时的。一旦对象被 parentPointer 指向,我想确保删除 mychild 指针(只是指针而不是对象)。
我不确定当它超出范围时是否会发生这种情况,因为指针是在 'new' 的上下文中声明的。
需要手动删除mychild指针吗?如果是这样,如何在不导致 parentPointer 越界的情况下删除指针?
考虑以下代码。
#include <iostream>
using namespace std;
class A { };
class B: public A { };
class C: public A { };
ostream &operator<<(ostream &os, const A &){ return os << 'A'; }
ostream &operator<<(ostream &os, const B &){ return os << 'B'; }
ostream &operator<<(ostream &os, const C &){ return os << 'C'; }
int main(){
A *a1=new B;
A *a2=new C;
cout << *a1 << *a2 << '\n';
}
它将打印 AA
,而不是 BC
。即使指针 a1
和 a2
确实指向类型 B
和 C
的对象,它们仍然是“指向 A
的指针”类型,并且当您将 *
运算符应用于它们时,表达式将具有 A
.
类型
要真正锻炼对象多态性,你应该使用虚函数。
class A {
public:
virtual char getName() const { return 'A'; }
};
class B {
public:
char getName() const { return 'B'; }
};
class C {
public:
char getName() const { return 'C'; }
};
ostream &operator<<(ostream &os, const A &a_like){
return os << a_like.getName();
}
// remove ostream &operator<<(ostream &os, const B &)
// remove ostream &operator<<(ostream &os, const C &)
编辑:最后,由于您提到没有内存泄漏并且还将指向派生类型对象的指针存储在指向基类型的指针集合中,您可能需要也使您的析构函数 virtual
。通过这样做,在销毁指针(通过 delete
运算符)或对基类型的引用时释放的资源将对派生类型的实际底层对象执行必要的清理操作。
另外不要忘记,如果您有类似 vector<SomeClass *>
的内容,指针元素在 vector 容器销毁时不会单独 delete
d。您应该在 vector 被销毁之前显式 delete
每个元素,用智能指针(例如 unique_ptr
或 shared_ptr
)包围您的指针,或者为您的多态对象创建您自己的 RAII 信封,也许知道移动操作。
本题中:
我遇到这样一种情况,父指针指向由前面的条件语句确定的两个可能对象之一。这是代码:(重新发布解决方案)
ClassParent *parentPointer; //Declare pointer to parent
if (condition) {
ClassChild1* mychild = new mychild1(); //Initialize ClassChild1 object with pointer mychild
parentPointer = mychild;//Parent pointer points to child1
}
if (!condition) {
ClassChild2* mychild = new mychild2(); //Initialize ClassChild1 object with pointer mychild
parentPointer = mychild;//Parent pointer points to child2
}
cout << *parentPointer;
问题是,我的对象是用 mychild 指针创建的,但我希望这个指针是临时的。一旦对象被 parentPointer 指向,我想确保删除 mychild 指针(只是指针而不是对象)。
我不确定当它超出范围时是否会发生这种情况,因为指针是在 'new' 的上下文中声明的。
需要手动删除mychild指针吗?如果是这样,如何在不导致 parentPointer 越界的情况下删除指针?
考虑以下代码。
#include <iostream>
using namespace std;
class A { };
class B: public A { };
class C: public A { };
ostream &operator<<(ostream &os, const A &){ return os << 'A'; }
ostream &operator<<(ostream &os, const B &){ return os << 'B'; }
ostream &operator<<(ostream &os, const C &){ return os << 'C'; }
int main(){
A *a1=new B;
A *a2=new C;
cout << *a1 << *a2 << '\n';
}
它将打印 AA
,而不是 BC
。即使指针 a1
和 a2
确实指向类型 B
和 C
的对象,它们仍然是“指向 A
的指针”类型,并且当您将 *
运算符应用于它们时,表达式将具有 A
.
要真正锻炼对象多态性,你应该使用虚函数。
class A {
public:
virtual char getName() const { return 'A'; }
};
class B {
public:
char getName() const { return 'B'; }
};
class C {
public:
char getName() const { return 'C'; }
};
ostream &operator<<(ostream &os, const A &a_like){
return os << a_like.getName();
}
// remove ostream &operator<<(ostream &os, const B &)
// remove ostream &operator<<(ostream &os, const C &)
编辑:最后,由于您提到没有内存泄漏并且还将指向派生类型对象的指针存储在指向基类型的指针集合中,您可能需要也使您的析构函数 virtual
。通过这样做,在销毁指针(通过 delete
运算符)或对基类型的引用时释放的资源将对派生类型的实际底层对象执行必要的清理操作。
另外不要忘记,如果您有类似 vector<SomeClass *>
的内容,指针元素在 vector 容器销毁时不会单独 delete
d。您应该在 vector 被销毁之前显式 delete
每个元素,用智能指针(例如 unique_ptr
或 shared_ptr
)包围您的指针,或者为您的多态对象创建您自己的 RAII 信封,也许知道移动操作。