当类的最后一个实例被破坏/覆盖时调用函数
Calling function when last instance of class is destructed / overwrited
我正在尝试创建一个类包装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
}
这里有两种解决方案,可以协同工作。
首先,不允许分配或复制"文件句柄"类。
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>
传递实例,该实例执行您尝试实现的引用计数类型 - 当最后一个std::shared_ptr
本身被破坏时,File
将被删除(因此调用其析构函数(。
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()
功能,我更倾向于将其作为成员函数,以便其用法是明确的,而不是在您不打算这样做时自动发生。
您可以使用
共享指针作为删除器fclose
:
#include <cstdio>
#include <memory>
#include <stdexcept>
class File
{
private:
typedef std::shared_ptr<FILE> shared_file;
public:
// You might consider const char*
File(const std::string& FileName, const std::string& Mode)
: F(std::fopen(FileName.c_str(), Mode.c_str()), fclose)
{
if( ! F.get()) {
throw std::runtime_error("File Open Failure");
}
}
private:
shared_file F;
};
int main()
{
File File1("/tmp/test.txt", "r");
auto File2 = File1;
}
相关文章:
- 当覆盖存在时调用基本虚拟"binded to object"函数
- 如何使基类从子类调用覆盖函数
- 我可以调用从 main() 覆盖的虚拟函数吗?
- 为什么调用具有通用或 r 值引用的重载覆盖函数是不明确的?
- 有没有办法调用基类函数,该函数在使用私有继承的派生类中被覆盖?
- 调用Main将替换矢量对象并覆盖数据
- C++如何抛弃函数的虚拟性并调用基本函数,而不是覆盖
- 在 C++ vs Java 中从构造函数调用被覆盖的方法
- 在UE4中,为什么我们需要覆盖BeginPlay,为什么我们需要在被覆盖的BeginPlay中调用Super::Begi
- 覆盖方法并用shared_ptr调用它们的奇怪行为
- 多重继承:调用所有覆盖的函数
- SVML的覆盖功能调用
- 覆盖数组元素时如何调用构造函数
- C 从同一基本模板类覆盖功能,具有多个继承模棱两可的函数调用
- 为什么没有调用我的覆盖方法
- C++ - 调用子项方法覆盖父项列表中的内容
- 每个方法调用上都覆盖了本地变量指针
- 通过引用调用虚函数:派生类的覆盖被调用
- 是否可以覆盖(隐藏)非虚拟方法,但仍然从子类显式调用它
- 堆栈上的对象被覆盖时未调用析构函数