#include <iostream>

#define A_WITH_SHOWPATH


#if 1 // helpers
struct PainterPath { };
class PathVisual
{
protected:
    PainterPath *mpPath;
    PathVisual(PainterPath *pPath) : mpPath(pPath) { }
public:
    virtual void setVisible() = 0;
    PainterPath* Path() const { return mpPath; }
};
class PathGraphic : public PathVisual
{
public:
    PathGraphic(PainterPath *p) : PathVisual(p) { }
    virtual void setVisible() override { std::cout << "show graphic\n"; } // would display path graphic
};
class PathWidget : public PathVisual
{
public:
    PathWidget(PainterPath *p) : PathVisual(p) { }
    virtual void setVisible() override { std::cout << "show widget\n"; } // would display path widget
};
#endif // helpers



class A
{
#ifdef A_WITH_SHOWPATH
private:
    std::string mPath;
public:
    void setPath(std::string const &path) {
        mPath = path;
        std::cout << "path set to '" << mPath << "'\n";
        showPath();
    }

    virtual void showPath() = 0; // to be called from outside, supposed to display mPath
#endif	
};

class B : public A
{
protected:
    PainterPath *mpPath;
    B(PainterPath *pPath) : mpPath(pPath) { }
public:
    virtual void showPath() = 0; // to be called from outside
};

class C_g : public B {
    PathGraphic *mpGraphic;
public:
    C_g(PathGraphic *pGraphic) : B(pGraphic->Path()), mpGraphic(pGraphic) { }
	
    virtual void showPath() override {
        mpGraphic->setVisible();
    }
};
	
class C_w : public B {
    PathWidget *mpWidget;
public:
    C_w(PathWidget *pWidget) : B(pWidget->Path()), mpWidget(pWidget) { }
    virtual void showPath() override {
        mpWidget->setVisible();
    }
};
	

int main() {
    PainterPath p;
    PathGraphic pg(&p);
    PathWidget pw(&p);
    B* b_g = new C_g(&pg);
    B* b_w = new C_w(&pw);

    std::cout << "Should say 'show graphic':\n";
    b_g->showPath();
    std::cout << "---------------------------\n";
    std::cout << "Should say 'show widget':\n";
    b_w->showPath();
    std::cout << "---------------------------\n";


#ifdef A_WITH_SHOWPATH
    std::cout << "Should say \"path set to 'Test'\", but not 'show graphic':\n";
    b_g->setPath("Test");
    std::cout << "# Calling setPath(\"/root\") on a B pointer now also displays the PainterPath, which is not the intended behavior.\n";
    std::cout << "---------------------------\n";
#endif


    return 0;
}
