#include <iostream>
class Base {
protected:
virtual std::ostream & print(std::ostream& stream) const {
stream << "Base class output\n";
return stream;
}
public:
// Define it only for the base class.
friend std::ostream & operator<<(std::ostream & stream, const Base & obj) {
return obj.print(stream);
}
virtual ~Base() {}
};
class A : public Base {
std::ostream & print(std::ostream & stream) const {
this->Base::print(stream);
stream << "foo = " << foo << "\n";
return stream;
}
int foo = 0;
public:
~A() {}
};
class B : public Base {
std::ostream & print(std::ostream & stream) const {
this->Base::print(stream);
stream << "bar = " << bar << "\n";
return stream;
}
int bar = 0;
public:
~B() {}
};
int main(int argc, char * argv[]) {
Base * base = new Base();
A * a = new A();
B * b = new B();
Base * a_inside = dynamic_cast<Base *>(a);
std::cout << *base << "\n";
std::cout << *a << "\n";
std::cout << *b << "\n";
std::cout << *a_inside << "\n";
delete base;
delete a;
delete b;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKY2xhc3MgQmFzZSB7CiAgIHByb3RlY3RlZDoKICAgICAgdmlydHVhbCBzdGQ6Om9zdHJlYW0gJiBwcmludChzdGQ6Om9zdHJlYW0mIHN0cmVhbSkgY29uc3QgewogICAgICAgICBzdHJlYW0gPDwgIkJhc2UgY2xhc3Mgb3V0cHV0XG4iOwogICAgICAgICByZXR1cm4gc3RyZWFtOwogICAgICB9CiAgIHB1YmxpYzoKCiAgICAgIC8vIERlZmluZSBpdCBvbmx5IGZvciB0aGUgYmFzZSBjbGFzcy4KICAgICAgZnJpZW5kIHN0ZDo6b3N0cmVhbSAmIG9wZXJhdG9yPDwoc3RkOjpvc3RyZWFtICYgc3RyZWFtLCBjb25zdCBCYXNlICYgb2JqKSB7CiAgICAgICAgIHJldHVybiBvYmoucHJpbnQoc3RyZWFtKTsKICAgICAgfQoKICAgICAgdmlydHVhbCB+QmFzZSgpIHt9Cn07CgpjbGFzcyBBIDogcHVibGljIEJhc2UgewoKICAgc3RkOjpvc3RyZWFtICYgcHJpbnQoc3RkOjpvc3RyZWFtICYgc3RyZWFtKSBjb25zdCB7CiAgICAgIHRoaXMtPkJhc2U6OnByaW50KHN0cmVhbSk7CiAgICAgIHN0cmVhbSA8PCAiZm9vID0gIiA8PCBmb28gPDwgIlxuIjsKICAgICAgcmV0dXJuIHN0cmVhbTsKICAgfQoKICAgaW50IGZvbyA9IDA7CiAgIHB1YmxpYzoKICAgfkEoKSB7fQp9OwoKY2xhc3MgQiA6IHB1YmxpYyBCYXNlIHsKCiAgIHN0ZDo6b3N0cmVhbSAmIHByaW50KHN0ZDo6b3N0cmVhbSAmIHN0cmVhbSkgY29uc3QgewogICAgICB0aGlzLT5CYXNlOjpwcmludChzdHJlYW0pOwogICAgICBzdHJlYW0gPDwgImJhciA9ICIgPDwgYmFyIDw8ICJcbiI7CiAgICAgIHJldHVybiBzdHJlYW07CiAgIH0KCiAgIGludCBiYXIgPSAwOwogICBwdWJsaWM6CiAgIH5CKCkge30KfTsKCgppbnQgbWFpbihpbnQgYXJnYywgY2hhciAqIGFyZ3ZbXSkgewogICBCYXNlICogYmFzZSA9IG5ldyBCYXNlKCk7CiAgIEEgKiBhID0gbmV3IEEoKTsKICAgQiAqIGIgPSBuZXcgQigpOwogICBCYXNlICogYV9pbnNpZGUgPSBkeW5hbWljX2Nhc3Q8QmFzZSAqPihhKTsKCiAgIHN0ZDo6Y291dCA8PCAqYmFzZSA8PCAiXG4iOwogICBzdGQ6OmNvdXQgPDwgKmEgPDwgIlxuIjsKICAgc3RkOjpjb3V0IDw8ICpiIDw8ICJcbiI7CiAgIHN0ZDo6Y291dCA8PCAqYV9pbnNpZGUgPDwgIlxuIjsKCiAgIGRlbGV0ZSBiYXNlOwogICBkZWxldGUgYTsKICAgZGVsZXRlIGI7CgogICByZXR1cm4gMDsKfQo=