C++ 重载操作符 <<实现模拟输出语句: cout << endl;

一、模拟 endl 输出换行并将缓冲区的数据刷新输出到屏幕显示

#include <iostream>
#define Stream std::basic_ostream<T1, T2>&

template<typename T1, typename T2>
Stream CRLF(Stream _out)
{
	putchar('\n');
	return _out.flush(); //清缓冲区 
}

int main(void)
{
	std::cout << "第一行" << CRLF;  //已脱离std::空间 
	CRLF(std::cout);  //还可以这样调用,单独输出一空行 
	std::cout << "第三行" << CRLF;
	//std::cout << "第四行" << endl; //必须用std::endl 
	
	return 0;
}

/*
第一行
        //第二行是空行
第三行

--------------------------------
Process exited after 1.197 seconds with return value 0
请按任意键继续. . .
*/

以下这样的代码更简洁:

#include <iostream>

std::ostream& endl (std::ostream& _os)
{
	_os.put('\n');
	_os.flush();
	return _os;
}

int main(void)
{
	std::cout << 1 << endl <<endl;	//这是自定义的 endl 
	std::cout << 2 << std::endl;	//这是std的 endl 
	
	endl(std::cout);			//这是自定义的 endl 
	std::cout << "========" << endl;

	std::endl(std::cout);		//这是std的 endl 
	std::cout << "========" << std::endl;
	
	return 0;
}

/*
1

2

========

========

--------------------------------
Process exited after 0.9518 seconds with return value 0
请按任意键继续. . .
*/

二、重载操作符 << 模拟输出语句: cout << 123 << "abc\n" << endl;

#include <iostream>
#include <string>
#include <typeinfo>
#define endl "\n"

class myOutText{
public:
    myOutText &operator << (auto s) {
		std::string str;
		if (typeid(s).name()==typeid(std::string("")).name()) str=s;
		if (str==endl) { 
			std::cout << endl;
			std::cout.flush();
		}
		else
			std::cout << s ;

		//return *this; //返回自身引用以支持连续操作
    }
};

int main(void)
{
    myOutText cout; 

	auto a = "abc";
	double b = 8.9;
	cout << "string1-" << a;
    cout << endl;
    cout << "1<<23<<4.56:" << endl;
    cout << 1 << 23 << 4.56e-7 << " "
		 << b << endl << "crlf" << endl;
		 
	std::string str = "endl";
    cout << str << endl << endl;
	        
    return 0;
}

/*
string1-abc
1<<23<<4.56:
1234.56e-007 8.9
crlf
endl


--------------------------------
Process exited after 1.198 seconds with return value 0
请按任意键继续. . .
*/

关于<<重载后连续使用的问题还上思否去请教过,感谢TianSong小哥的指点:使用 return *this 返回自身引用。在此放出经他修改过的代码:

#include <iostream>

class myOutText{
public:
    myOutText &operator << (auto s) {
        std::cout << s;
    	return *this;
    }

    myOutText &operator << (void(*obj)(myOutText&)) {
    	obj(*this);
        return *this;
    }
 
    void flush() {
        std::cout.flush();
    }
};

void endl(myOutText &obj) 
{
    obj << '\n';
    obj.flush();
}

int main(void)
{
    myOutText cout; 
	std::string str="abcd";
    cout << "string<<" << str << endl;
    cout << "1<<2<<" << endl <<endl;
    cout << 1 << 2.3 << str << endl; 
        
    return 0;
}

/*
string<<abcd
1<<2<<

12.3abcd

--------------------------------
Process exited after 0.4635 seconds with return value 0
请按任意键继续. . .
*/

TianSong的赠言和遵循的原则,也值得学习:

梅耶(Scott Meyers) 的经典名言 “恭喜大家,坐上了通往未定义道路的宇宙飞船”。

我遵循的两条原则:

  • 编译器警告即错误(除非十分清楚);
  • 违背基础语法、理论的事不做。

附:

例程二用到了操作符 typeid ,详细用法请见: 《用 typeid 操作符 做一个C++数据类型大全

猜你喜欢

转载自blog.csdn.net/boysoft2002/article/details/114222330
今日推荐