我正在开发一个c ++应用程序。 在我的代码中,我有一个对象指针 TestClass * pObj = new TestClass(); 和成员函数调用像pObj-> close(); 在close()成员函数内部,我应该将pObj设为NULL。 根据我们的要求,TestClass用户不应该在pObj上调用delete。(TestClass的析构函数是专门为此目的而私有的) 此外,TestClass不应公开任何静态方法来接收指针并使其为NULL。
有没有其他方法可以在调用close()后将pObj设为NULL?
我试过一种方法。 在close()函数内部,我使用const_cast删除了此指针的constness。 并参考了它。 然后我做了这个= NULL。 即使再调用一边,pObj指针值仍然存在。它没有设置为NULL。 这可能是由于该指针的地址和pObj的地址不同。 请帮助。 编辑:对不起,我错过了什么。在一个名为init的静态函数中调用new。 init函数如下所示。 void init(TestClass *& pObj);因此,TestClass用户首先调用init进行分配。但他不能叫deinit(不应该有任何这样的功能)实际上,这不是我的设计。我进入这个项目时就出现了:(答案 0 :(得分:10)
想象一下这样的代码:
TestClass *ptr1 = new TestClass();
TestClass *ptr2 = ptr1;
ptr2->close();
您希望将哪个指针设置为null?在close
方法内部,您无法获知有多少指针指向您的对象以及如何访问close
方法。
答案 1 :(得分:8)
鉴于你的约束,没有办法做你想做的事。
一个警告:如果您的类的用户在堆栈上的对象上创建会发生什么:TestClass test;
?
还有一个问题,为什么你希望你的班级用户被迫拨打new
来分配你班级的对象,然后禁止拨打delete
。对我毫无意义。
答案 2 :(得分:4)
根据我们的要求,TestClass用户不应该在pObj上调用delete。(TestClass的析构函数是故意为此目的而私有的)另外,TestClass不应该暴露任何静态方法来接收指针并使其为NULL。
谁设定了这些要求?对于他们每个人,问“为什么?”。他们似乎绝对武断,没有任何意义。
和成员函数调用如pObj-> close();在close()成员函数内部,我应该将pObj设为NULL。
再次,“为什么?”。忽略从函数内部改变它是不可能的,使用这样的风格是疯狂的。正常的C ++方式是破坏对象。
如果你的“为什么”得不到合理的答案,你应该考虑辞掉这份工作,或者准备好在挫折中度过你的时间。你提出的设计“要求”非常疯狂。
答案 3 :(得分:4)
疯狂的问题需要一个疯狂的解决方案,所以这里有一个。你不能完全按照自己的意愿去做,因为跟踪对象的原始指针是不可能的。但是,如果使用某种智能指针,则可以在销毁对象时跟踪它们并使其无效。这是在较少疯狂情况下的常见要求,因此已经有智能指针来执行此操作:shared_ptr
以保持对象存活,并weak_ptr
跟踪对象并在其被销毁时变为空。所以解决方案看起来像这样:
class TestClass
{
public:
static weak_ptr<TestClass> create()
{
shared_ptr<TestClass> shared(new TestClass);
shared->self = shared;
return shared;
}
void close()
{
self.reset();
}
private:
shared_ptr<TestClass> self;
};
int main()
{
weak_ptr<TestClass> object = TestClass::create();
weak_ptr<TestClass> copy = object;
assert(!object.expired());
assert(!copy.expired());
object.lock()->close();
assert(object.expired());
assert(copy.expired());
}
答案 4 :(得分:3)
没有。请考虑以下代码:
TestClass * const pObj = new TestClass();
pObj->close();
编译器将不拒绝代码,即使close为const
。指针是const,但不是新的TestClass对象。因此,您可以通过指针调用非const方法,但是您无法更改指针本身。这意味着你也不能将它设置为NULL。
答案 5 :(得分:2)
它基本上意味着您需要将this
指针设置为NULL。据我所知,这是不可能的。如果它有帮助你可以认为调用方法按值this
指针,即你在方法中做的任何改变都不会反映在外面。
答案 6 :(得分:2)
当你编写可怕的代码时,你可以在从close()返回之前添加一些内联汇编和xor ecx,ecx
。
答案 7 :(得分:2)
除非你碰巧对pObj init过于谨慎,否则可能无法正常工作。
#include <map>
std::map<TestClass*, TestClass**> pointers();
void init(TestClass *& pObj)
{
pObj = new TestClass();
pointers[pObj] = &pObj;
}
void TestClass::Close()
{
*pointers[this] = null;
pointers.erase(this);
delete this;
}
答案 8 :(得分:0)
虽然它充满了危险,但可能是一种方式
TestClass::Close(Testclass *&p){
p = NULL;
}
pObj->close(pObj);
编辑:解释限制Close();
pObj是否可以在'TestClass :: Close'的范围内访问?例如命名空间范围变量? 如果是,TestClass :: Close方法可以简单地设置pObj = NULL;
如果不是,恕我直言