我正在尝试创建一个包装 fopen()/fclose()/f* 方法的类。我想将此方法用于其他目的,这就是我不想使用智能指针的原因。
问题是我不知道何时调用 fclose() 或其他“生命终结”函数。可以调用析构函数,但同时 FILE * 被复制到另一个对象,例如通过复制构造函数。
我尝试编写“引用计数器”类(这将是所有类的基类)但不幸的是我无法从构造函数/析构函数调用纯虚方法。
这是我试过的:
class ReferenceCounter
{
public:
ReferenceCounter()
{
ReferenceCount = new unsigned int(0);
AddRef();
}
ReferenceCounter(const ReferenceCounter & CopyFrom)
{
ReferenceCount = CopyFrom.ReferenceCount;
AddRef();
}
ReferenceCounter & operator = (const ReferenceCounter & AssignFrom)
{
RemoveRef();
ReferenceCount = AssignFrom.ReferenceCount;
AddRef();
return *this;
}
~ReferenceCounter()
{
RemoveRef();
}
virtual void OnInit() = 0;
virtual void OnDestruct() = 0;
private:
unsigned int * ReferenceCount;
void AddRef()
{
if(++*ReferenceCount == 1)
OnInit();
}
void RemoveRef()
{
if(--*ReferenceCount == 0)
{
OnDestruct();
delete ReferenceCount;
}
}
};
也许有一种方法可以“覆盖”或“覆盖”一个类?
例子:
class File
{
public:
File(std::string FileName)
{
F = fopen(FileName.c_str(), ...);
}
~File()
{
fclose(F);
}
private:
FILE * F;
};
int main()
{
File File1("a.txt");
auto File2 = File1;
//SegFault = fclose called twice for File1 and File2
}
最佳答案
这里有两个协同工作的解决方案。
首先,不允许分配或复制“文件句柄”类。1
class File
{
// C++11 solution: use =delete
public:
File(File & const) = delete;
File & operator=(File & const) = delete;
// C++ < 11 solution: make them private and *don't implement them*:
private:
File(File & const);
File & operator=(File & const);
};
其次,考虑只传递对单个 File
的引用目的。 (编译器不会再让您复制 File
对象,所以如果您不小心这样做,您会遇到编译器错误——这很好,因为它会帮助您确定需要修复的区域。)
如果建立单一所有权点太困难,请考虑使用 std::shared_ptr<File>
传递实例这正是您要实现的那种引用计数——File
当最后一个 std::shared_ptr
时将被删除(因此它的析构函数被调用)本身就被破坏了。
auto file = std::make_shared(new File{"a.txt"});
auto file2 = file;
// file.use_count() and file2.use_count() are now both 2.
//
// When file2 is destructed this will drop to 1; when file is destructed this will
// drop to 0, and the File object will be deleted.
1 请注意,您可能可以使用 dup()
实现复制, 尽管赋值的语义可能有点棘手——赋值应该关闭现有句柄和 dup()
正在分配的句柄?如果你执行 dup()
功能 我更倾向于将其设为成员函数,这样它的用法就很明确,而不是在您可能不希望它这样做时自动发生。
关于c++ - 当类的最后一个实例被破坏/覆盖时调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26044592/