C ++插入<<操作员超载

时间:2014-11-11 05:50:22

标签: c++ operator-overloading operators overloading cout

我如何(在外部函数中)区分cout<< thingToShow和outfile<< thingToWrite有不同的格式? 我有一个文件,我应该在不改变任何东西的情况下构建所有这些实现,并且有

的实例
    cout << "\nx matrix is: \n";
    cout << x;
    cout << "\ny matrix is: \n";
    cout << y;

应该格式化为

x matrix is: 
         ---              ---
        |       30  50      |
        |                   |
        |       25  40      |
         ---              ---


y matrix is: 
         ---              ---
        |       2   3       |
        |                   |
        |       1   1       |
         ---              ---

我有

的实例
w = r * w;

outfile << w;

应该被简单地格式化为

-20    40
-80    60

我的实施是

ostream& operator<< (ostream &out, const Matrix& y){
    out << "\t\t" << " ---\t\t\t\t    ---\n"<< "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n\t\t|\t\t\t\t\t|\n\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n" << "\t\t" << " ---\t\t\t\t    ---\n\n";
    return out;
}

适用于标准cout&lt;&lt; thingToShow输出格式,但显然会弄乱outfile&lt;&lt; thingToWrite格式。 我可以在if语句中放入(stream&amp; out,)参数的属性吗?或者是否有其他方法来区分cout和outfile?

3 个答案:

答案 0 :(得分:2)

您可以测试ostream是否为cout:

if (&out == &std::cout)

您可以采取适当的行动,具体取决于结果。但是如果你想要我未经请求的意见,我认为最好让用户决定如何打印出来,使用某种格式化的类:

std::cout << format(my_matrix, fancy);
outfile << format(my_matrix, not_fancy);

在此示例中,format将是一个函数,它返回某个类的对象,该对象包含Matrix对象(通过引用)和格式化选项。此类将重载operator<<,以根据给定的选项为流生成适当的输出。或者,您可以制作自己的专用I / O操纵器。

答案 1 :(得分:0)

您需要保持一些状态不足以决定输出是短格式还是长格式。我认为,维护这些数据的最佳位置是班级Matrix本身。

然后,提供可用于设置格式的功能。您还可以提供重载的operator<<功能,以便将其与ostream一起使用。

这是一个有效的版本。

#include <iostream>

struct Matrix
{
   int tl;
   int tr;
   int bl;
   int br;

   static void setLongFormat();

   static void setShortFormat();

   enum OutputFormat
   {
      LONG_FROMAT,
      SHORT_FORMAT
   };

   static OutputFormat outputFormat;
};

Matrix::OutputFormat Matrix::outputFormat = Matrix::SHORT_FORMAT;

void Matrix::setLongFormat()
{
   outputFormat = LONG_FROMAT;
}

void Matrix::setShortFormat()
{
   outputFormat = SHORT_FORMAT;
}

std::ostream& operator<< (std::ostream &out, const Matrix& y)
{
   if ( Matrix::outputFormat == Matrix::LONG_FROMAT )
   {
      out << "\t\t" << " ---\t\t\t\t    ---\n"
         << "\t\t|\t\t"<<y.tl<< "\t"<<y.tr<< "\t\t|\n"
         << "\t\t|\t\t\t\t\t|\n"
         << "\t\t|\t\t"<<y.bl<< "\t"<<y.br<< "\t\t|\n"
         << "\t\t" << " ---\t\t\t\t    ---\n\n";
   }
   else
   {
      out << y.tl<< "\t" << y.tr<< "\n"
         << y.bl<< "\t" << y.br<< "\n";
   }

   return out;
}

std::ostream& operator<<(std::ostream &out, void (*fun)())
{
   fun();
   return out;
}


int main()
{
   Matrix a{30, 50, 25, 40};
   std::cout << Matrix::setLongFormat << a << std::endl;
   std::cout << Matrix::setShortFormat << a << std::endl;
};

输出:

         ---                    ---
        |       30  50      |
        |                   |
        |       25  40      |
         ---                    ---


30  50
25  40

PS。这些标签在这里看起来不太合适。我确信可以修改该功能以使标签保持在正确的位置。

答案 2 :(得分:0)

不像我想的那么容易。

可以通过重载std::ifstream来完成。这意味着您必须为所有类型重载它,因此除了Matrix重载之外,还需要一个包含所有模板的重载。

struct Matrix
{
    int a, b;
};

// Matrix for std::cout
std::ostream& operator<<(std::ostream& os, const Matrix& t)
{
    os << "[\n\t" << t.a << "\n\t" << t.b << "\n]";
    return os;
}

// overload of general types for files
template<typename Type>
std::ofstream& operator<<(std::ofstream& ofs, const Type& t)
{
    // this cast prevents infinite recursion
    static_cast<std::ostream&>(ofs) << t;
    return ofs;
}

// Matrix overload for files
std::ofstream& operator<<(std::ofstream& ofs, const Matrix& t)
{
    // this cast prevents infinite recursion
    static_cast<std::ostream&>(ofs) << "{" << t.a << ", " << t.b << "}";
    return ofs;
}

int main()
{
    std::ofstream ofs("test.txt");

    Matrix m {3, 7};

    std::cout << 4 << m << 9 << '\n';
    ofs << 4 << m << 9 << '\n';
}

输出:std :: cout

4[
    3
    7
]9

输出:ofs

4{3, 7}9

注意:此方法区分std::ofstream及其父类std::ostream。这意味着如果您希望在函数中使用此行为,则必须将显式类型std::ifstream传递给任何函数。