我一直在尝试将<<(cout)和>>(cin)运算符重载一段时间用于一类复数,我在.h文件中给出了原型.
这是我在class.cpp文件中尝试这样做的:
std::istream &operator>> (std::istream &in, complex& c) { double h, j; in >> h >> j; c.set(h,j); return in; } std::ostream &operator<<(std::ostream &out, complex c) { out << c.getReal; out << c.getImag; return out; }
这的确是我第一次见过的std:: istream
和std:: ostream
,而不是cout和cin和我真的不知道如何cout <<
和 cin >>
都相关
我尝试在main.cpp文件上测试它,但我得到错误
本>>
应该吸收复杂的论证到复杂的类参数和改变私有成员的值real
和imag
不确定我是否应该在这里使用我的设置功能
这是我给出的原型.h文件:
#ifndef COMPLEX_H #define COMPLEX_H class complex { public: complex(); complex(double a); complex(double a, double b); complex(int a, int b); void print() const; void set(double a = 0, double b = 0); void set(int a = 0, int b = 0); double getReal() const; double getImag() const; void get(double&, double&) const; complex operator+ (double& x); complex operator+ (complex&); complex operator+= (complex&); complex operator+= (int&); complex operator++ (int); complex operator++ (); complex operator- (double&); complex operator- (complex&); complex operator-= (complex&); complex operator-= (double&); complex operator-- (int); complex operator-- (); complex operator* (complex&); complex operator* (double&); complex operator*= (complex&); complex operator*= (double&); complex operator/ (complex&); complex operator/= (complex&); complex operator/= (double); complex operator/ (double); void operator= (const complex&); bool operator== (complex&); bool operator!=(complex &c); friend std::istream &operator>> (std::istream &in, complex& c); friend std::ostream &operator<<(std::ostream &out, complex c); /*complex conj() const; double norm() const; double modulus() const; */ private: double real; double imag; }; #endif // COMPLEX_H
有人能告诉我如何适当地超载吗?
好的,我现在正在尝试输出a + bi:
std::ostream& operator<< (std::ostream& out, complex const& c) { return out << c.getReal() << "+" << c.getImag() << "i"; }
并输入:
std::istream& operator>> (std::istream& in, complex& c) { double h, j; if (in >> h >> "+" >> j >> "i") { c.set(h, j); } return in; }
但是,当我编译时,我收到以下错误:
这是我的complex.cpp文件(类复杂实现文件)的第181行,其中if (in >> h >> "+" >> j >> "i") {
位于上面的函数定义中:
binary '>>': no operator found which takes a right-hand operand of type 'const char [2]' (or there is no acceptable conversion)
以下是针对friend std::istream &operator>> (std::istream &in, complex& c);
原型所在的complex.h文件的第45行(注意每个错误是单独的,总共7行).
'istream':is not a member of 'std' syntax error missing ';' before '&' 'istream':'friend' not permitted on data declarations missing type specifier-int assumed. Note:C++ does not support default-int unexpected token(s) preceding';' namespace "std" has no member "istream" namespace "std" has no member "istream"
以下是我的complex.h文件的第46行所在
friend std::ostream &operator<<(std::ostream &out, complex c);
位于
'ostream': is not a member of 'std' syntax error: missing ';' before '&' 'ostream':'friend' not permitted on data declarations missing type specifier -int assumed.Note: C++ does not support default-int unexpected token(s) preceding ';' namespace "std" has no member "ostream" namespace "std" has no member "ostream"
我注意到两者都是同一类型的错误.请注意我有
#includeusing namespace std;
都在complex.cpp文件和main.cpp文件中
让我们从简单的东西开始:std::cin
是一个派生类型的实例std::istream
.类似地,std::cout
是从中派生的类型的实例std::ostream
.这些流类型是否曾经有过的东西,你可以重载的输入和输出操作符(你应该不试图从他们那里获得改变自己的行为-这是用做std::streambuf
).还有其他流类型,例如std::ifstream
/ std::ofstream
(用于读取/写入文件)和std::istringstream
/ std::ostringstream
(用于读取/写入字符串).
接下来要看的是输出操作符:对于初学者,在调用成员函数时需要括号.您还需要在两个值之间使用分隔符,否则实部和虚部可能会相互融合.我可能会将运算符实现为
std::ostream& operator<< (std::ostream& out, complex const& value) { return out << value.getReal() << " " << value.getImag(); }
使用空格而不使用其他分隔符通常可能不是最理想的,但使阅读更容易.对于实际的实现复杂类的我可能会使用的格式书写真正+
IMAGi
或(
实际,
IMAG)
但这些是很难解析.
在尝试读取值之后,应始终检查从流中读取值.例如,代码可能如下所示:
std::istream& operator>> (std::istream& in, complex& c) { double h, j; if (in >> h >> j) { c.set(h, j); } return in; }
除了丢失的检查之外,输入函数看起来没问题,假设两个值由空格分隔:在尝试读取值之前,默认情况下会使用输入运算符跳过空格.如果使用某些分隔符将值格式化得更加精美,则需要单独处理这些分隔符.这样做的代码可能如下所示:
templatestd::istream& skip_char(std::istream& in) { if ((in >> std::skipws).peek() != C) { in.setstate(std::ios_base::failbit); } else { in.ignore(); } return in; } std::istream& (*const open_parenthesis)(std::istream&) = &skip_char<'('>; std::istream& (*const close_parenthesis)(std::istream&) = &skip_char<')'>; std::istream& (*const comma)(std::istream&) = &skip_char<','>; std::istream& operator<< (std::istream& in, complex& c) { double real, imag; if (in >> open_parenthesis >> real >> comma >> imag >> close_parenthesis) { c.set(real, imag); } return in; }
这些有趣的实体open_parenthesis
,close_parenthesis
并且comma
是初始化为指向函数模板实例的函数指针skip_char
.他们有一个特定的签名,使他们有资格成为操纵者.当"读入"一个操纵器时,相应的函数被调用它们被"读取"的流.也就是说,例如std::cin >> comma
,调用comma(std::cin)
实际上是一个调用skip_char<','>(std::cin)
.但是,我想对于这项任务,全面的方法有点矫枉过正.