求助关于fstream重载问题

you_kind 2010-08-12 05:07:09
在搞一个日志类

class logger: public fstream
{
public:
logger ()
{
open("logfile",ios::app|ios::out);
}

~logger ()
{
close();
}
}

logger log_; //全局对象

//调用
log_ << "log something here " << endl;


我想日志写到文件的时候,自动在前面加上时间,应该怎么做?
重载 << 操作符 ,是针对输出的对象, 好像达不到目的
高手指点下~ 谢谢!
...全文
265 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
失落的凡凡 2010-08-14
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 you_kind 的回复:]

<< 重载成成员函数或是全局函数, 我试了下都可以, 不知为啥说在全局函数里好些?
还有一个问题,无论哪种方法 重载后 输出, logger << std::endl 会出错,应该是 std::endl 在模板里不能被确定出类型, 有啥解决办法? 谢谢~
[/Quote]

对于标准库的ostream , operator必须写成全局函数的。这是因为这样可以重载自定义类型的输出,而如果是ostream的成员函数,则无法重载(重载就要修改ostream的实现)。 对于自己写的log类,operator<<写成成员函数还是全局函数都无所谓,反正它是调用了ostream的operator<<, 用户只需要重载ostream相关的operator<<就可以了。
you_kind 2010-08-13
  • 打赏
  • 举报
回复
<< 重载成成员函数或是全局函数, 我试了下都可以, 不知为啥说在全局函数里好些?
还有一个问题,无论哪种方法 重载后 输出, logger << std::endl 会出错,应该是 std::endl 在模板里不能被确定出类型, 有啥解决办法? 谢谢~
thatway_c 2010-08-13
  • 打赏
  • 举报
回复
std::ofstream coutStream ("./log/cout.log");
std::streambuf* stdStream = std::cout.rdbuf(coutStream.rdbuf())
std::cout << "hello world!" << std::endl;
std::cout.rdbuf(stdStream);
djjlove_2008 2010-08-13
  • 打赏
  • 举报
回复
哈哈,这个设计模式本身就不太好,还是不继承fstream,你就直接用MFC中的封装东东来写,简单些。
jackyjkchen 2010-08-13
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 you_kind 的回复:]
额 谢谢楼上们~
stream 系列的类 本身就有一个继承关系的吧? 如fstream本身就是继承 ifstream 和 ofstream 来的,这个地方虚析构是怎么解决的?
我的初衷还是希望能够以流的方式记log 。。
[/Quote]
STL内部有多态的地方当然有虚析构,但是fstream这样最终面向用户的类根本不希望用户再去继承他
you_kind 2010-08-13
  • 打赏
  • 举报
回复
额 谢谢楼上们~
stream 系列的类 本身就有一个继承关系的吧? 如fstream本身就是继承 ifstream 和 ofstream 来的,这个地方虚析构是怎么解决的?
我的初衷还是希望能够以流的方式记log 。。
失落的凡凡 2010-08-13
  • 打赏
  • 举报
回复
不用继承, 用has-a 实现

#include <fstream>
#include <string>

using namespace std;

class logger
{
public:
logger ()
{
m_LogFile.open("logfile.txt",ios::app|ios::out);
}

~logger ()
{
m_LogFile.close();
}

template<class T>
friend logger& operator<<(logger&, T obj);
private:
fstream m_LogFile;

};

template <class T>
logger& operator<< (logger& log, T obj)
{
log.m_LogFile << "time now : " << obj << endl;
return log;
}


/*
logger& operator << (logger& log, const char* pstr)
{
log.m_LogFile << "time now : " << pstr << endl;
return log;
}
*/
logger log_; //全局对象

int main()
{
//调用
log_ << "log something here ";
return 0;
}
  • 打赏
  • 举报
回复
学习学习
adventurelw 2010-08-13
  • 打赏
  • 举报
回复
直接重载<<不可以吗?
you_kind 2010-08-13
  • 打赏
  • 举报
回复
额 用继承方式设计是不好。。。
改了下代码


class log_me
{
public:
log_me()
{
buf.open("log.test",ios::app|ios::out);
}

~log_me()
{
buf.close();
}

template< class type> log_me & operator<<( type val)
{
buf << val ;
return *this;
}

void operator() (const char* format, ...)
{
if(!LOG_DEBUG)
return;
FILE* logfile = fopen("log.test", "a");
char time_[32];
get_time(time_);
fprintf(logfile, "[%s]\t", time_);

va_list ap;
va_start(ap, format);
vfprintf(logfile, format, ap);
va_end(ap);

fclose(logfile);
}

log_me& operator() ()
{
char time_[32];
get_time(time_);
buf << "[" << time_ << "]\t";
return *this;
}

private:
void get_time(char* time_)
{
time_t nCurrTime;
struct tm stCurrTime;
::time(&nCurrTime);
::localtime_r(&nCurrTime, &stCurrTime);
::sprintf(time_, "%d%02d%02d %02d:%02d:%02d",
stCurrTime.tm_year+1900, stCurrTime.tm_mon+1, stCurrTime.tm_mday,
stCurrTime.tm_hour, stCurrTime.tm_min, stCurrTime.tm_sec);
}

fstream buf;
};


调用的时候 可以直接支持
logger() << "stream style log test\n" ;
或者
logger("c style log test\n");

这样基本达到目的了 哈哈
cattycat 2010-08-12
  • 打赏
  • 举报
回复
确实,stl的类不要自己继承,写日志还是自己写一个函数,IO性能比stl的好,用宏实现比较好。
liutengfeigo 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 jackyjkchen 的回复:]
记得看过某本书,说STL不应该继承使用,其中特别点了string和stream
[/Quote]
对,因为他们的析构函数不是虚的
jackyjkchen 2010-08-12
  • 打赏
  • 举报
回复
记得看过某本书,说STL不应该继承使用,其中特别点了string和stream
CyberLogix 2010-08-12
  • 打赏
  • 举报
回复
重载 << 操作符必须些成全局函数或者友元函数
Jim_King_2000 2010-08-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 you_kind 的回复:]

谢谢 Jim_King_2000~
我目的是 像用流一样来写日志, 如 log_ << "some string " << some_obj << some_int_val ... 这样,添其他成员函数, 会破坏原先的写法。。。
[/Quote]
那就自己写一个stream buffer类,然后去处理行。比较麻烦……
云瑀 2010-08-12
  • 打赏
  • 举报
回复
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
class logger
{
private:
string _data;
string _time;
public:
logger (string data)
{
_data = data;
time_t rawtime;
struct tm * timeinfo;

time ( &rawtime );
timeinfo = localtime ( &rawtime );
_time = asctime (timeinfo);
_time[_time.size()-1] = ' ';
}

friend ostream& operator <<(ostream& os, logger* log)
{
os << "[" << log->_time << "]:" << log->_data;
return os;
}

~logger ()
{
}
};


int _tmain(int argc, _TCHAR* argv[])
{
cout<<new logger("test")<<endl;
system("pause");
return 0;
}

用ostream示范...可吗?
懒得弄档案...
you_kind 2010-08-12
  • 打赏
  • 举报
回复
谢谢 Jim_King_2000~
我目的是 像用流一样来写日志, 如 log_ << "some string " << some_obj << some_int_val ... 这样,添其他成员函数, 会破坏原先的写法。。。
Jim_King_2000 2010-08-12
  • 打赏
  • 举报
回复
fstream是流,它只负责把字符源源不断的往文件里送。而你的log文件有行的概念。因此不适合用operator<<。你可以为logger加一个成员函数writeLine,用它来写文件。
you_kind 2010-08-12
  • 打赏
  • 举报
回复
额 不行的。。 我是想每一次 调 log_ << "..." << endl 时 打印出实时的时间
hai040 2010-08-12
  • 打赏
  • 举报
回复
在构造函数里写?

64,282

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧