0

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?

1 Answers1

1

Using this way of polymorphic calls in C++ requires to use reference sematics. I advise to read about it. E.g.: Reference and Value 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?.

wohlstad
  • 12,661
  • 10
  • 26
  • 39