1

在我的代码中,Manager派生自Employee并且它们中的每一个都有一个operator<<覆盖。

class Employee{
protected:
    int salary;
    int rank;
public:
    int getSalary()const{return salary;}
    int getRank()const{return rank;}
    Employee(int s, int r):salary(s), rank(r){};
};
ostream& operator<< (ostream& out, Employee& e){
    out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
    return out;
}

class Manager: public Employee{
public:
    Manager(int s, int r): Employee(s, r){};
};
ostream& operator<< (ostream& out, Manager& m){   
    out << "Manager: ";
    cout << (Employee)m << endl;  //can not compile, how to call function of Employee?
    return out;
}

我希望cout << (Employee)m << endl;会打电话ostream& operator<< (ostream& out, Employee& e),但它失败了。

4

6 回答 6

8

转换为引用而不是副本:

cout << (Employee&)m << endl;  //can not compile, how to call function of Employee?

另请注意,ostream 运算符绝不是该类的成员(您似乎对问题的标题感到困惑)。

于 2013-10-31T15:35:55.717 回答
4

这样做的通常方法是在派生类可以覆盖的基类中具有(可能privateprotected)虚拟print(或任何其他合适的名称)函数。

您只提供operator<<对基类的引用并print在其中调用的一般性。如果需要,覆盖print函数可以调用 base 的。print

于 2013-10-31T15:36:14.577 回答
4

更改cout << (Employee)m << endl;cout << (Employee&)m << endl;

错误信息的解释是这样的:

当您尝试 cast(Employee)m时,您正在创建一个临时的。重载operator<<需要引用。您不能引用临时文件。

由于您真的只是希望它打印自己的数据(而不是复制自身),因此您将拥有的引用转换为所需类型的引用(它是基类)。

正如 jrok 在他的回答中指出的那样,您也可以通过提供一个虚拟函数来打印数据来实现这一点。这将是一种更简单的方法,因为它不需要您operator<<为每个派生类重载。

于 2013-10-31T15:40:26.250 回答
1

你的超载:

ostream& operator<< (ostream& out, Employee& e)

仅适用于对Employee对象的引用,因此它不适用于非引用值(如强制转换的结果)。

通常,原型是:

ostream& operator<< (ostream& out, const Employee& e)

这也保证了打印 Employee 不会改变它。如果你改变它,事情应该会正常工作。(必须是引用,而不是 const 引用,因为ostream& 打印ostream操作会改变。)

于 2013-10-31T15:39:22.950 回答
0

首先,你重载了一个全局函数。这是除覆盖之外的另一个概念。请参阅C++ 中的覆盖和重载

接下来,你的演员阵容是错误的。这应该这样做:

ostream& operator<< (ostream& out, Manager& m){   
    out << "Manager: ";
    cout << static_cast<Employee&>(m) << endl;  //can not compile, [...]?
   return out;
}

...如果您真的想重载全局<<运算符。

于 2013-10-31T16:00:23.040 回答
0

有两个问题结合在一起使您的编译失败。

(1) 本声明及定义:

    ostream& operator<< (ostream& out, Employee& e){
        out << "Salary: " << e.getSalary() << " Rank: " << e.getRank() << endl;
        return out;
    }

尽管您没有更改e,但您将其引用为非const. 这禁止您在右值上调用此运算符。

(2)这条线

cout << (Employee)m << endl;

正如其他人所说,您正在切片m。此外,强制转换(Employee) m返回一个临时Employee值,它是一个右值。

总之,(Employee)m强制转换产生一个不能绑定到的右值e

您可以修复一个或另一个以使您的代码编译器,但最好解决这两个问题以使您的代码更健壮:

// ...
ostream& operator<< (ostream& out, const Employee& e) {
// ...

// ...
cout << static_cast<Employee&>(m) << endl;
// ...
于 2013-10-31T15:52:01.187 回答