Pergunta

In my code, Manager is derived from Employee and each of them have an operator<< override.

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;
}

I hoped cout << (Employee)m << endl; would call ostream& operator<< (ostream& out, Employee& e), but it failed.

Foi útil?

Solução

Cast to a reference instead of a copy:

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

Also note the ostream operator is in no way member of the class(it seems you are confused about that from the title of the question).

Outras dicas

Change cout << (Employee)m << endl; to cout << (Employee&)m << endl;.

The explanation of the error message is this:

When you attempt the cast (Employee)m, you are creating a temporary. The operator<< overload takes a reference. You cannot take a reference to a temporary.

Since you really just want it to print it's own data (not make a copy of itself), you cast the reference you have to the reference of the type you need (it's base class).

As jrok pointed out in his answer, you can also accomplish this by providing a virtual function to print the data. That would be a simpler approach as it would not require you to overload operator<< for every derived class.

The usual way of doing this is to have (a possibly private or protected) virtual print (or any other suitable name) function in the base class that derived classes can override.

You only provide general operator<< for a reference to the base class and call print inside it. The overriding print functions can call the base's print, if need be.

Your overload:

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

only works for references to Employee objects, so it won't work on non-reference values (like the result of a cast).

Normally, the prototype would be:

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

which also provides the reassurance that printing an Employee doesn't mutate it. If you change that, things should work just fine. (ostream& does have to be a reference, not a const reference, because the ostream is mutated by the print operation.)

There are two problems which combined make your compilation to fail.

(1) This declaration and definition:

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

Despite you don't change e, you take it reference to non-const. This forbids you calling this operator on an rvalue.

(2) This line

cout << (Employee)m << endl;

As said by others you are slicing m. In addition, the cast (Employee) m returns a temporary Employee which is an rvalue.

In summary, the cast (Employee)m yields an rvalue which cannot bind to e.

You can fix either one or the other to make your code compiler but it's better to fix both problems to make your code more robust:

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

// ...
cout << static_cast<Employee&>(m) << endl;
// ...

First, you overload a global function. This is another concept than overriding. see Override and overload in C++

Next, your cast is wrong. This should do:

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

...if you really want to overload the global << operator.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top