Я пытаюсь создать программу, в которой пользователь дважды щелкает по экрану, и прямоугольник рисуется в соответствии с тем, что было нажато.
Сейчас все, что я пытаюсь сделать, это настроить мои классы так, чтобы они могли правильно рисовать прямоугольник вручную, не беспокоясь о том, где пользователь нажимает.
Со временем моя программа сможет рисовать такие вещи, как круги и треугольники, поэтому я решил использовать полиморфизм и иметь каждый тип фигуры (т.е. Rectangle
) быть своим собственным классом, который наследует от класса с именем Shapes
,
У меня тогда есть класс под названием Game
который содержит Shapes
объект.
Shapes.h
#ifndef _shapes_h_
#define _shapes_h_
#include <vector>
#include "glut.h"
class Shapes
{
public:
void DrawAll() const;
void Add(Shapes * shape);
virtual void Draw() const {}
protected:
std::vector<Shapes *> mShapes;
};
#endif
Shapes.cpp
#include "Shapes.h"#include <iostream>
void Shapes::DrawAll() const
{
int i;
for (i = 0; i < mShapes.size(); i++)
{
mShapes[i]->Draw();
}
}
void Shapes::Add(Shapes * shape)
{
mShapes.push_back(shape);
}
Rectangle.h
#ifndef _rectangle_h_
#define _rectangle_h_
#include "Shapes.h"
class Rectangle : public Shapes
{
public:
Rectangle(std::vector<int> p1, std::vector<int> p2);
void Draw() const;
private:
std::vector<int> mP1;
std::vector<int> mP2;
};
#endif
Rectangle.cpp
#include "Rectangle.h"#include <iostream>
Rectangle::Rectangle(std::vector<int> p1, std::vector<int> p2)
{
mP1 = p1;
mP2 = p2;
}void Rectangle::Draw() const
{
std::cout << "Draw Me " << std::endl;
glColor3d(0, 0, 0);
glBegin(GL_QUADS);
glVertex2d(mP1[0], mP1[1]);
glVertex2d(mP2[0], mP1[1]);
glVertex2d(mP2[0], mP2[1]);
glVertex2d(mP1[0], mP2[1]);
glEnd();
}
Game.h
#ifndef _game_h_
#define _game_h_
#include <vector>
#include "Shapes.h"
class Game
{
public:
void Click(int x, int y);
void Draw();
private:
Shapes mTest;
};
#endif
Первый Game.cpp ниже написан так, как я пытаюсь сделать, но он выдает ошибку Unhandled exception at 0x001AF742 in Shapes.exe: 0xC0000005: Access violation reading location 0x00000001.
Посмотрев на это, я обнаружил, что некоторая переменная скрытого указателя __vfptr (которая, я думаю, управляет виртуальными вещами) устанавливается в 0 и вызывает проблемы с памятью.
Заметка, Click()
вызывается только при нажатии мыши, Draw()
вызывается каждый раз, когда происходит событие любого типа (например, нажатие мыши, отпускание мыши, нажатие клавиши, отпускание клавиши и т. д.). При нажатии мыши вызываются оба события, но Click()
вызывается первым.
Также, mTest
переменная, которая является объектом Shapes.
Game.cpp: не работает
#include "Game.h"#include "Rectangle.h"#include <iostream>
void Game::Click(int x, int y)
{
std::vector<int> p1;
p1.push_back(200);
p1.push_back(200);
std::vector<int> p2;
p2.push_back(250);
p2.push_back(250);
Rectangle rect(rp1, rp2);
Shapes * rectangle = ▭
mTest.Add(rectangle);
}
void Game::Draw()
{
mTest.DrawAll();
}
Однако, что, кажется, сбивает с толку меня, если я добавляю прямоугольник формы к mTest
внутри Draw()
функционировать прямо перед тем, как я позвоню DrawAll()
, оно работает. Тем не менее, я хочу иметь возможность создавать прямоугольник в зависимости от того, где пользователь нажимает, и этот метод этого не допустит.
Game.cpp: работает
#include "Game.h"#include "Rectangle.h"#include <iostream>
void Game::Click(int x, int y)
{
}
void Game::Draw()
{
std::vector<int> p1;
p1.push_back(200);
p1.push_back(200);
std::vector<int> p2;
p2.push_back(250);
p2.push_back(250);
Rectangle rect(rp1, rp2);
Shapes * rectangle = ▭
mTest.Add(rectangle);
mTest.DrawAll();
}
В классе Shapes заменить
std::vector<Shapes *> mShapes;
от
std::vector<std::shared_pointer<Shapes>> mShapes;
Чем заменить код
Rectangle rect(rp1, rp2);
Shapes * rectangle = ▭
mTest.Add(rectangle);
от
mTest.Add(std::make_shared<Rectangle>(rp1, rp2));
И, наконец, заменить определение метода
void Shapes::Add(Shapes * shape)
от
void Shapes::Add(std::shared_ptr<Shapes> shape)
Это делает ваш код работает.
Описание: Если вам нужны указатели, подумайте об умных указателях (std :: unique_ptr, упомянутый @ user657267, тоже умный указатель). Вы можете прочитать об умных указателях во многих местах, Вот а также Вот. Для лучшего дизайна, не забывайте о шаблонах дизайна.