gpt4 book ai didi

c++ - 如何使 ostream 引用成为 ofstream? (C++)

转载 作者:可可西里 更新时间:2023-11-01 16:29:21 24 4
gpt4 key购买 nike

我正在尝试制作一个简单的记录器类,我希望能够记录到通用 ostream(cout/cerr) 或一个文件。我想到的设计是允许构造函数采用 ostream& 或文件名,在后一种情况下创建 ofstream& 并将其分配给类的私有(private)ostream& 像这样:

class Log {
private:
std::ostream& os;
public:
Log(std::ostream& os = std::cout): os(os) { }
Log(std::string filename) {
std::ofstream ofs(filename);
if (!ofs.is_open())
// do errorry things
os = ofs;
}
};

这样做会给我一个错误,即 ofstream 的赋值运算符是私有(private)的。再看一遍,我突然想到,引用一个本地对象可能行不通,让 os 成为一个指向 ostream 的指针,然后声明并删除它在堆上使用 ofstream 情况,但不是 ostream 情况,其中 ostream 已经存在并且只是被 os (因为删除 os 的唯一地方是在构造函数中,我不知道有什么方法可以确定 os 是否是指向是否在堆上创建的 ofstream

那么我怎样才能使它工作,即让 os 引用一个在构造函数中用文件名初始化的 ofstream

最佳答案

一方面,引用一旦创建就不能重新绑定(bind),只能初始化它们。你可能认为你可以这样做:

Log(std::string filename) : os(std::ofstream(filename)) {
if (!os.is_open())
// do errorry things
}

但这并不好,因为您正在使 os 引用一个临时变量。

当你需要一个必须是可选的引用时,也就是说,它有时需要引用某些东西而不是其他时候,你真正需要的是一个指针 :

class Log {
private:
std::ostream* os;
bool dynamic;
public:
Log(std::ostream& os = std::cout): os(&os), dynamic(false) { }
Log(std::string filename) : dynamic(true) {
std::ofstream* ofs = new std::ofstream(filename);

if (!ofs->is_open())
// do errorry things and deallocate ofs if necessary

os = ofs;
}

~Log() { if (dynamic) delete os; }
};

上面的例子只是为了告诉你发生了什么,但你可能会想用一个智能指针来管理它。正如 Ben Voigt 指出的那样,有很多问题会导致您的程序出现无法预料和不希望出现的行为;例如,当你试图复制上面的类时,它会很麻烦。这是上面使用智能指针的示例:

class Log {
private:
std::unique_ptr<std::ostream, std::function<void(std::ostream*)>> os;
public:
Log(std::ostream& os = std::cout): os(&os, [](ostream*){}) { }

Log(std::string filename) : os(new std::ofstream(filename), std::default_delete<std::ostream>()) {
if (!dynamic_cast<std::ofstream&>(*os).is_open())
// do errorry things and don't have to deallocate os
}
};

不寻常的 os(&os, [](ostream*){}) 使指针指向给定的 ostream& 但当它超出范围时什么都不做;它给了它一个什么都不做的删除函数。您也可以在没有 lambda 的情况下执行此操作,只是对于此示例而言更容易。

关于c++ - 如何使 ostream 引用成为 ofstream? (C++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9459136/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com