重载插入运算符(运算符<<)

时间:2013-12-17 21:41:44

标签: c++

我需要你的帮助,因为我似乎无法理解SO上和其他网站上关于插入操作符重载的任何(许多)各种解决方案。

我要创建一个“数据库”,由一个单独的向量组成的员工,除其他外,我必须能够保存到文本文件。

代码必须有一个名为Employees的基类和三个名为Manager,Engineer和Researcher的派生类。

基于:

for (vector<Employees*>::iterator i = midzer.begin(); i != midzer.end(); ++i)
{
    (*i)->printStats(); 
}

/* printStats is a virtual method outputting all data contained in the objects to 
the console window. It's implemented like so for one of the derived classes:*/

void Manager::printStats()
{
    cout << "\nManager." << endl;
    cout << "First name: " << mFirstName << endl; // data member of base class
    cout << "Last name: " << mLastName << endl; // data member of base class
    cout << "Salary: " << mSalary << endl; // data member of base class
    cout << "Meetings per week: " << mNumberOfMeetingsPerWeek << endl; // data member of derived class
    cout << "Vacation Days per year: " << mNumberOfVacationDaysPerYear << endl; //data member of derived class
    cout << endl;
}

我以为我可以像下面那样创建一个ostream对象瞧..

ofstream outfile;
outfile.open("/users/mundt/desktop/EmployeeDatabase.txt");
for (vector<Employees*>::iterator i = midzer.begin(); i != midzer.end(); ++i)
{
    outfile << (*i)->printStats();
}
outfile.close();

正如您(可能)知道这是不可能的,我必须为基类Employees重载插入运算符,并使其多态以某种方式能够访问派生类部分。

我正在寻找的是一种使用printStats()方法将矢量中所有对象的数据输出到文本文件的方法。

如果有人可以提供一些示例代码来执行此操作,将非常感谢。谢谢。

3 个答案:

答案 0 :(得分:2)

首先,应告知printStats将数据放在何处,而不是始终将其写入cout

void Manager::printStats(std::ostream& out) const //function doesn't modify, so const
{
    out << "\nManager." << endl;
    out << "First name: " << mFirstName << endl; // data member of base class
    out << "Last name: " << mLastName << endl; // data member of base class
    out << "Salary: " << mSalary << endl; // data member of base class
    out << "Meetings per week: " << mNumberOfMeetingsPerWeek << endl; // data member of derived class
    out << "Vacation Days per year: " << mNumberOfVacationDaysPerYear << endl; //data member of derived class
    out << endl;
}

然后告诉C ++如何将您的类插入流中:

std::ostream& operator<<(std::ostream& out, const Employees& employee) 
{
   employee.printStats(out);
   return out; //return ostreams by reference when done
}

如果您愿意,可以为矢量添加另一个,这几乎与您的旧循环完全相同

std::ostream& operator<<(std::ostream& out, const vector<Employees*>& midzer) 
{
   for (vector<Employees*>::const_iterator i = midzer.begin(); i != midzer.end(); ++i)
   {
       out << *(*i);
   }
   //or if you have a newer compiler:
   //for (Employees* i : midzer) out << *i;
   return out; //return ostreams by reference when done
}

最后,输出矢量

ofstream outfile;
outfile.open("/users/mundt/desktop/EmployeeDatabase.txt");
outfile << midzer; //well that's easy
outfile.close();

此处的演示演示:http://coliru.stacked-crooked.com/a/03fd3b4e23dc7ee2

答案 1 :(得分:2)

这样做有很多选择,我将描述3:

  1. 从函数
  2. 返回一个字符串
  3. 输出到传递给函数的流
  4. 重载operator<<(与上述2之一结合使用)
  5. 更多细节:

    1. 如果您从printStats()函数返回一个字符串,那么您可以将其写入ofstream

      std::string Manager::printStats()
      {
          std::stringstream ss;
          ss << "\nManager." << endl;
          ss << "First name: " << mFirstName << endl; // data member of base class
          ss << "Last name: " << mLastName << endl; // data member of base class
          ss << "Salary: " << mSalary << endl; // data member of base class
          ss << "Meetings per week: " << mNumberOfMeetingsPerWeek << endl; // data member of derived class
          ss << "Vacation Days per year: " << mNumberOfVacationDaysPerYear << endl; //data member of derived class
          ss << endl;
      
          return ss.str();
      }
      
    2. 如果您将ostream传入此功能,则可以直接输出到该功能。 (您可能希望将该函数定义为void printStats( std::ostream& os = std::cout );,因此如果您在没有参数的情况下调用它,它将默认为cout

      void Manager::printStats( std::ostream& os )
      {
          os << "\nManager." << endl;
          //...
      }
      

      在你的例子中会这样调用:

      (*i)->printStats( outFile );
      
    3. 如果您重载operator<<,则可以直接将其传递给outFile

      std::ostream& operator<<( std::ostream& os, const Employee& e )
      {
          os << e.printStats(); 
          // or
          e.printStats( os );
      
          // for both cases
          return os;
      }
      

      然后可以这样称呼:

      outFile << *(*i);
      

答案 2 :(得分:0)

cout是函数ostream正在打印的特定PrintStats。您正在寻找的是为您的类型重载operator<<

    std::ostream & operator<<(std::ostream & s, const Employee& m)
    {
        m.Stream(s);
        return s;
    }

然后这可以用作:

    outfile << *i;

然后在virtual Stream() const中声明一个函数Employee并在Manager

中覆盖它