#include <iostream>
#include <memory>
//---------------------------------------------------------------------------------------
// keep interfaces abstract (no implementation yet)
class IBaseNode
{
public:
virtual ~IBaseNode() = default; // classes with virtual methods must also have virtual destructors.
virtual void BasicFunc() = 0;
};
// allow mixin of default implementation (CRTP)
// this way you will not fall into the trap
// of creating a design with diamond inheritance later
template<typename base_t>
class IBaseNodeImpl :
public IBaseNode
{
public:
virtual void BasicFunc()
{
// do not use std::endl; unless you really have to flush
// in templates you need to use this
std::cout << "BaseNode BasicFunc(), value = " << this->m_value << "\n";
}
private:
int m_value{ 42 };
};
//---------------------------------------------------------------------------------------
class IVisibility
{
public:
virtual ~IVisibility() = default;
virtual void Draw() const = 0;
};
template<typename base_t>
class IVisibilityImpl :
public IVisibility
{
public:
void Draw() const override
{
std::cout << "Visibility Draw()\n";
if (get_visibility())
{
std::cout << "Visible\n";
}
else
{
std::cout << "Invisible\n";
}
}
protected:
// never expose private members directly
// for refactorability later
void set_visibility(bool is_visible)
{
m_is_visible = true;
}
bool get_visibility() const noexcept
{
return m_is_visible;
}
private:
bool m_is_visible{ false };
};
//---------------------------------------------------------------------------------------
class Rectangle final :
public IBaseNodeImpl<Rectangle>,
public IVisibilityImpl<Rectangle>
{
public:
Rectangle()
{
std::cout << "Rectangle constructed\n";
// You can manage visibility from within
// the rectangle too
set_visibility(true);
}
~Rectangle()
{
std::cout << "Rectangle destructed\n";
}
};
int main() {
//BaseNode* pRect = new Rectangle; <== don't use new in C++ anymore, you should use std::make_unique (to avoid memory leaks)
std::unique_ptr<IBaseNode> rectangle = std::make_unique<Rectangle>();
rectangle->BasicFunc();
auto visibility = dynamic_cast<IVisibility*>(rectangle.get());
visibility->Draw();
return 0;
}