C ++ Проблемы полиморфизма. Что-то делать с _vfptr

Я пытаюсь создать программу, в которой пользователь дважды щелкает по экрану, и прямоугольник рисуется в соответствии с тем, что было нажато.

Сейчас все, что я пытаюсь сделать, это настроить мои классы так, чтобы они могли правильно рисовать прямоугольник вручную, не беспокоясь о том, где пользователь нажимает.

Со временем моя программа сможет рисовать такие вещи, как круги и треугольники, поэтому я решил использовать полиморфизм и иметь каждый тип фигуры (т.е. 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 = &rect;
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 = &rect;
mTest.Add(rectangle);
mTest.DrawAll();
}

0

Решение

В классе Shapes заменить

std::vector<Shapes *> mShapes;

от

std::vector<std::shared_pointer<Shapes>> mShapes;

Чем заменить код

Rectangle rect(rp1, rp2);

Shapes * rectangle = &rect;
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, тоже умный указатель). Вы можете прочитать об умных указателях во многих местах, Вот а также Вот. Для лучшего дизайна, не забывайте о шаблонах дизайна.

1

Другие решения


По вопросам рекламы [email protected]