#include <iostream>
#include <memory>
using namespace std;
//Extras
class ShapeExtra
{
public:
ShapeExtra() {}
void ShapeFunc() { std::cout << "Shape"; }
virtual ~ShapeExtra() = default; //Important!
};
class Shape
{
public:
std::unique_ptr<ShapeExtra> m_var;
//require a pointer on construction
//make sure to document, that Shape class takes ownership and handles deletion
Shape(ShapeExtra* p):m_var(p){}
//The common functions
ShapeExtra& GetVar(){ return *m_var; }
void ShapeFunc() {m_var->ShapeFunc();}
};
class CircleExtra : public ShapeExtra
{
public:
void CircleExtraFunc() {std::cout << "Circle";}
};
class Circle : public Shape
{
CircleExtra* m_var;
public:
Circle() : Shape(new CircleExtra()) {
m_var = static_cast<CircleExtra*>(Shape::m_var.get());
}
void CircleFunc()
{
m_var->CircleExtraFunc();
}
};
int main() {
Circle c;
//use the ShapeExtra Object
c.GetVar().ShapeFunc();
//call via forwarded function
c.ShapeFunc();
//call the circleExtra Function
c.CircleFunc();
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8bWVtb3J5Pgp1c2luZyBuYW1lc3BhY2Ugc3RkOwoKLy9FeHRyYXMKY2xhc3MgU2hhcGVFeHRyYQp7CiAgICBwdWJsaWM6CiAgICBTaGFwZUV4dHJhKCkge30KICAgIHZvaWQgU2hhcGVGdW5jKCkgeyBzdGQ6OmNvdXQgPDwgIlNoYXBlIjsgfQogICAgdmlydHVhbCB+U2hhcGVFeHRyYSgpID0gZGVmYXVsdDsgLy9JbXBvcnRhbnQhCn07CgpjbGFzcyBTaGFwZQp7CiAgICBwdWJsaWM6CiAgICBzdGQ6OnVuaXF1ZV9wdHI8U2hhcGVFeHRyYT4gbV92YXI7CgoJLy9yZXF1aXJlIGEgcG9pbnRlciBvbiBjb25zdHJ1Y3Rpb24KCS8vbWFrZSBzdXJlIHRvIGRvY3VtZW50LCB0aGF0IFNoYXBlIGNsYXNzIHRha2VzIG93bmVyc2hpcCBhbmQgaGFuZGxlcyBkZWxldGlvbgoJU2hhcGUoU2hhcGVFeHRyYSogcCk6bV92YXIocCl7fQoJCiAgICAvL1RoZSBjb21tb24gZnVuY3Rpb25zCiAgICBTaGFwZUV4dHJhJiBHZXRWYXIoKXsgcmV0dXJuICptX3ZhcjsgfQogICAgdm9pZCBTaGFwZUZ1bmMoKSB7bV92YXItPlNoYXBlRnVuYygpO30KfTsKCgpjbGFzcyBDaXJjbGVFeHRyYSA6IHB1YmxpYyBTaGFwZUV4dHJhCnsKCXB1YmxpYzoKICAgIHZvaWQgQ2lyY2xlRXh0cmFGdW5jKCkge3N0ZDo6Y291dCA8PCAiQ2lyY2xlIjt9Cn07CgpjbGFzcyBDaXJjbGUgOiBwdWJsaWMgU2hhcGUKewoJQ2lyY2xlRXh0cmEqIG1fdmFyOwoJCiAgICBwdWJsaWM6CiAgICBDaXJjbGUoKSA6IFNoYXBlKG5ldyBDaXJjbGVFeHRyYSgpKSB7CiAgICAJbV92YXIgPSBzdGF0aWNfY2FzdDxDaXJjbGVFeHRyYSo+KFNoYXBlOjptX3Zhci5nZXQoKSk7IAogICAgfQoKICAgIHZvaWQgQ2lyY2xlRnVuYygpCiAgICB7CiAgICAgICAgbV92YXItPkNpcmNsZUV4dHJhRnVuYygpOwogICAgfQp9OwoKCmludCBtYWluKCkgewoJQ2lyY2xlIGM7CgkvL3VzZSB0aGUgU2hhcGVFeHRyYSBPYmplY3QKCWMuR2V0VmFyKCkuU2hhcGVGdW5jKCk7CgkvL2NhbGwgdmlhIGZvcndhcmRlZCBmdW5jdGlvbgoJYy5TaGFwZUZ1bmMoKTsKCS8vY2FsbCB0aGUgY2lyY2xlRXh0cmEgRnVuY3Rpb24KCWMuQ2lyY2xlRnVuYygpOwoJcmV0dXJuIDA7Cn0=