Home > OS >  OOP in C . How to drop the states
OOP in C . How to drop the states

Time:04-07

I am writing a simple graphics editor. There are 3 buttons on the panel, by pressing which I draw a square, circle or line. There are 3 button handlers that change the state and 3 mouse event handlers in the class responsible for drawing the workspace.

void Cpr111View::OnCirc()
{
    state = 1;
}
void Cpr111View::OnLine()
{
    state = 2;
}
void Cpr111View::OnRect()
{
    state = 3;
}

To shorten the question, I will give only one handler out of 3.

void Cpr111View::OnMouseMove(UINT nFlags, CPoint point)
{
    if (state==2)
    {
        int oldmode;
        CClientDC *pDC = new CClientDC(this);
        if (nFlags && MK_LBUTTON)
        {
            oldmode = pDC->GetROP2(); 
            pDC->SetROP2(R2_NOT); 
            pDC->MoveTo(begin.x, begin.y);
            pDC->LineTo(oldmouse.x, oldmouse.y);
            pDC->MoveTo(begin.x, begin.y);
            pDC->LineTo(point.x, point.y);
            oldmouse = point;
            pDC->SetROP2(oldmode); 
            CView::OnMouseMove(nFlags, point);
        }
    }
    if (state == 1)
    {
        ….
    }
    if (state == 3)
    {
        ….
    }
void Cpr111View::OnLButtonUp(UINT nFlags, CPoint point)
{
}
void Cpr111View::OnLButtonDown(UINT nFlags, CPoint point)
{
}

Here is a drawing system. I want to do it without states. That is, create an abstract class Figure. With three virtual methods per render:

Class Figure
{
public:
void virtual MouseMove()=0;
void virtual ButtonUp()=0;
void virtual ButtonDown()=0;
}

And from him in the classes of figures to override these methods.

Class Recatngle:public Figure
{
public:
void MouceMove() override;
...
}

Then, when the button is clicked, create an object of the corresponding class, then the button handler will look like this:

void Cpr111View::OnRect()
    {
        figure = new Rectangle();
    }

And when drawing, the mouse handler will simply call the method of the corresponding class:

void Cpr111View::OnMouseMove(UINT nFlags, CPoint point)
{
    figure - > MouseMove();
}

In order for figure to be available in two different methods, we declare it in the class:

class Cpr111View : public CView
{
public:
    Figure figure;
…
}

This is how I want to do it, but the problem is that it can't be done that way. At a minimum, you cannot declare an abstract class variable. Then what type should it be if I am going to write a pointer to different classes into it? How to implement this architecture correctly, or maybe there are better ideas?

CodePudding user response:

Using this way of polymorphic calls in C requires to use reference sematics. I advise to read about it. E.g.: https://isocpp.org/wiki/faq/value-vs-ref-semantics

So it class Cpr111View, you have to keep your Figure member by pointer, or by refernce.

In order to avoid having to manually manage the object, you should use a smart pointer like std::unique_ptr (or std::shared_ptr if you need to share ownership):

#include <memory> // for std::unique_ptr
class Cpr111View : public CView
{
public:
    std::unique_ptr<Figure> figure;
//…
}

Of course you will need to allocate it before using it. Instead of:

figure = new Rectangle();

use:

figure = std::make_unique<Rectangle>();

The method calls stay the same as in your code, e.g.:

figure->MouseMove();

If you not familiar with smart pointers in C , I recomend to read about it. E.g.: What is a smart pointer and when should I use one?

  • Related