Question

I got an unexpected result which I couldn't explain myself so far.

Although two times an object of the same class BASIC2 (inheriting from BASIC1) is generated a different message is generated when using the friend operator<< on the generated object.

See code below

I let D (object of a class Derived which inherits from Base) generate an object of class BASIC2 and call it's friend operator<<. This produces the expected message "BASIC2 object".

I let B generate an object of class BASIC1 and call its friend operator<<. This outputs "BASIC1 object" as I expected.

Then I use virtual inheritance to let B2 (Base* B2 = &D;) generate an object of BASIC2. I follow the code flow in the debugger (Visual Studio 2010) and this correctly generates an object of BASIC2. However, the friend operator<< is not called on the BASIC2 object, but uses the friend operator<< from class BASIC1 (and hence outputs "BASIC1 object").

Note also I do want BASIC2 to inherit from BASIC1 as I want to exploit the covariance behavior.

int main(int argc, char* argv[]) {
    Base B;
    Derived D;
    Base* B2 = &D;
    std::cout << *D.generate(0) << std::endl;
    std::cout << *B.generate(0) << std::endl;
    std::cout << *(B2->generate(0)) << std::endl;
    system("pause");
}

The output is:

BASIC2 object
BASIC1 object
BASIC1 object
class BASIC1 {
public:
    friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
    os << "BASIC1 object";
    return os;
    }
};

class BASIC2 : public BASIC1 {
    friend std::ostream& operator<<(std::ostream& os, const BASIC2& basic) {
    os << "BASIC2 object";
    return os;
    }
};

class Base {
public:
    virtual BASIC1* generate(double num) const {
    return new BASIC1();
    }
protected:
private:
};

class Derived : public Base {
public:
    virtual BASIC2* generate(double num) const override {
    return new BASIC2();
    }
protected:
private:
};
Was it helpful?

Solution

Selection of operator<< is based on static type of your object known during compilation time. To achieve what you want do not define two operator<< function, but one only in BASIC1:

    friend std::ostream& operator<<(std::ostream& os, const BASIC1& basic) {
      Write(os);
      return os;
    }

and define virtual function Write in both BASIC1 and BASIC2 to do what you want:

virtual void Write(std::ostream& os) const {
   os << "BASIC1 object";
}

OTHER TIPS

Thanks! For me the end conclusion of my question is: If you call friend operator<<(std::ostream& os, const Base& object) on an object in which the object is generated through dynamic dispatching. You need to use virtual functions in your operator<< to allow for dynamic dispatching of the operator<<.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top