6

C++ 标准库中有complex<>一个模板,它有一个重载的 << 运算符,因此它以 (real_part, im_part) 格式输出复数。我需要更改该运算符对复数的行为,以便将输出格式更改为完全不同的格式。具体来说,我需要输出格式为real_part\tim_part. 我怎么做?

4

5 回答 5

7

没有直接的替换方法operator <<,但您确实有一些选择。首先,您可以编写自己的函数来打印复数:

template <typename T> void PrintComplex(const complex<T>& c) {
    /* ... */
}

如果您仍想使用漂亮的流语法,那么您可以做的一个技巧是创建一个包装器类来包装 acomplex然后定义它自己operator <<的以不同的方式将其打印出来。例如:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    complex<T> c;
};

一旦你有了这个,你可以写类似的东西

cout << ComplexPrinter<double>(myComplex) << endl;

您可以通过编写一个像这样的函数来为您包装对象,从而使其更加简洁:

template <typename T>
ComplexPrinter<T> wrap(const complex<T>& c) {
    return ComplexPrinter<T>(c);
}

然后这让你写

cout << wrap(myComplex) << endl;

这并不完美,但非常好。

关于上述包装器需要注意的一点是,它设置了一个隐式转换构造函数,让您可以将complex<T>s 转换为ComplexPrinter<T>s。这意味着如果您有vector< complex<T> >,您可以通过调用使用自定义代码将其打印出来

vector< complex<double> > v = /* ... */
copy (v.begin(), v.end(), ostream_iterator< ComplexPrinter<double> >(cout, " "));

在输出时,隐式转换构造函数会将您complex<double>的 s 转换为包装器,而您的自定义代码将为您进行打印。

如果您想非常冒险并谨慎行事,您甚至可以编写该类,以便它只存储对原始 的引用complex,如下所示:

template <typename T> class ComplexPrinter {
public:
    /* Conversion constructor allows for implicit conversions from
     * complex<T> to ComplexPrinter<T>.
     */
    ComplexPrinter(const complex<T>& value) : c(value) {
        // Handled in initializer list
    }

    /* Output the complex in your own format. */
    friend ostream& operator<< (ostream& out, const ComplexPrinter& cp) {
        /* ... print in your own format ... */
    }

private:
    const complex<T>& c;
};

这完全消除了任何复制,只是使包装器成为真正的complex. (没有双关语的意思)。如果您这样做不会将这些对象传递到原始对象超出范围的范围边界,那么您必须非常小心,但如果这是您想要的,它可能会很好。

希望这可以帮助!

于 2011-02-14T07:08:44.523 回答
3
template<class T>
struct my_complex_format_type {
  std::complex<T> const &x;
  my_complex_format_type(std::complex<T> const &x) : x (x) {}
  friend std::ostream& operator<<(std::ostream &out,
                                  my_complex_format_type const &value)
  {
    out << "format value.x however you like";
    return out;
  }
};
template<class T>
my_complex_format_type<T> my_complex_format(std::complex<T> const &x) {
  return x;
}

void example() {
  std::cout << my_complex_format(some_complex);
}
于 2011-02-14T07:09:51.370 回答
1

对于 的任何特定实例化complex<T>,使用强 typedef(boost 有一个版本)并在 << 调用期间强制转换为该类型。覆盖该类型的 <<。

如果您需要为任何变化覆盖 <<,complex<T>那么生活将变得更加艰难。

于 2011-02-14T07:50:27.543 回答
0

我在这里对同一问题的回答:c++ display complex number with i in imaginary part产生了你想要的行为,但代价是未来不兼容的一些风险,因为它在命名空间中插入了一个模板特化std::

于 2018-10-19T12:45:20.513 回答
-1

没有真正整洁的方法可以做到这一点。我的建议是放弃 iostreams 并写一些更像 C 的东西。它可能会更快地写入,更快地读取和更快地执行。

于 2011-02-14T07:17:46.517 回答