例如,如果我想要一个带有
<<
的默认输出版本和详细版本。
myClass myObject(//Constructor parameters);
cout << myObject << "\n";
cout << myObject.detailed << "\n";
我尝试在我的班级中制作一个修饰符,但这似乎不起作用。
class myClass {
public:
friend std::ostream& operator<<(std::ostream& output, const myClass& myObject);
std::ostream& detailed(std::ostream& output);
}
这给出了错误“必须调用对非静态成员函数的引用”。
这是根据 iostreams 设计应该如何完成的。
#include <iostream>
class MyClass
{
static const int flagId; // private format flag
public:
int x, y; // for exposition only
static std::ios_base& detailed(std::ios_base& str) {
str.iword(flagId) = true;
return str;
}
static std::ios_base& abridged(std::ios_base& str) {
str.iword(flagId) = false;
return str;
}
friend std::ostream& operator<< (std::ostream& stream, const MyClass& myClassObj) {
if (stream.iword(flagId)) {
stream << "X=" << myClassObj.x << " Y=" << myClassObj.y;
// optionally reset the flag to false
} else {
stream << myClassObj.x;
}
return stream;
}
};
const int MyClass::flagId = std::ios_base::xalloc();
int main()
{
MyClass myObject{1, 42};
std::cout << MyClass::detailed << myObject << "\n";
std::cout << MyClass::abridged << myObject << "\n";
}
您无法将非静态类方法传递给
operator<<
,它不支持调用该方法的能力,因此会出现错误。
对于您尝试执行的操作,您需要将
detailed
更改为 stream manipulator 对象而不是成员函数,例如:
struct detailed {
const myClass &cls;
detailed(const myClass &cls) : cls(cls) {}
friend std::ostream& operator<<(std::ostream& os, const detailed& det) {
// print details about det.cls as needed...
return os;
}
};
myClass myObject(...);
cout << detailed(myObject) << "\n";
例如,这就是
std::(re)setiosflags
、std::set(base|fill|precision|w)
、std::quoted
等标准参数操纵器的实现方式。
我认为我的方法与@RemyLebeau 相同,但更通用。
#include <iostream>
#include <string>
//---------------------------------------------------------------------------------------------
// class templated to be able to apply
// detailed mechanism to different types
template<typename type_t>
class detailed
{
public:
detailed(const type_t& object) :
m_object{ object }
{
}
friend std::ostream& operator<<(std::ostream& os, const detailed<type_t>& detailed_object)
{
detailed_object.m_object.detailed_output(os);
return os;
}
private:
const type_t& m_object;
};
//---------------------------------------------------------------------------------------------
// like your class
struct test_class_t
{
public:
friend std::ostream& operator<<(std::ostream& os, const test_class_t& object)
{
os << object.basic;
return os;
}
void detailed_output(std::ostream& os) const // <- const is important
{
os << basic << ", " << details;
}
private:
std::string basic{ "basic" };
std::string details{ "details" };
};
//---------------------------------------------------------------------------------------------
int main()
{
test_class_t object;
std::cout << detailed{object} << "\n";
}