método substituído C ++ não sendo chamado
-
22-07-2019 - |
Pergunta
Shape.h
namespace Graphics {
class Shape {
public:
virtual void Render(Point point) {};
};
}
Rect.h
namespace Graphics {
class Rect : public Shape {
public:
Rect(float x, float y);
Rect();
void setSize(float x, float y);
virtual void Render(Point point);
private:
float sizeX;
float sizeY;
};
}
struct ShapePointPair {
Shape shape;
Point location;
};
Usado como esta:
std::vector<Graphics::ShapePointPair> theShapes = theSurface.getList();
for(int i = 0; i < theShapes.size(); i++) {
theShapes[i].shape.Render(theShapes[i].location);
}
Este código acaba chamando Shape::Render
e não Rect::Render
Estou assumindo que este é porque ele está lançando o Rect
a um Shape
, mas eu não tenho nenhuma idéia de como pará-lo fazendo isso. Eu estou tentando deixar que cada um controle da forma como ele é processado, substituindo o método Render
.
Algumas ideias sobre como conseguir isso?
Solução
Aqui está o problema:
struct ShapePointPair {
Shape shape;
Point location;
};
Você está armazenando um Shape
. Você deve estar armazenando um Shape *
, ou um shared_ptr<Shape>
ou algo assim. Mas não um Shape
; C ++ não é Java.
Quando você atribui um Rect
ao Shape
, apenas a parte Shape
está sendo copiado (isto é objeto corte ).
Outras dicas
Este problema é chamado de corte - você perde a funcionalidade derivado ao copiar para a base. Para evitar isso ponteiros de uso para a classe base, ou seja,
std::vector<Graphics::Shape*> s;
s.push_back(&some_rect);
O problema é que, em seu vetor você está armazenando cópias de objetos Shape, e copiar um objeto Shape não copia os dados ou funcionalidade de suas classes derivadas - você está corte o polimorfismo de distância.
Gerenciar os objetos usando novas e apagar e mandar para o seu vetor para armazenar ponteiros para eles.
O polimorfismo só irá funcionar a partir de um ponteiro para uma forma, não a partir de um objeto de forma.
Você está acessando o objeto de forma direta para a substituição para funcionar, você precisa acessar o objeto por meio de um ponteiro ou referências.
Por exemplo, quando você assigne a forma no ShapePointPair o código vai 'fatia' do objeto e só copiar o bit forma no ShapePointPair
Fazendo isso irá significar que você tem que prestar atenção gerenciamento de memória - assim você poderia usar um ponteiro inteligente na struct ShapePointPair { forma smart_pointer; Ponto de localização; };
Não, não está lançando.
Você pode, em vez armazenar uma referência a baseclass Point:
struct ShapePointPair {
Shape shape;
Point &location;
};
Esta referência deve ser definida em tempo de construção para struct ShapePointPair. Adicionar um construtor para ShapePointPair para este objetivo. Ele deve ser passado (recém-criada) casos de Rect.
Observe também as responsabilidades de gerenciamento de memória (própria destruidores escritas, etc.).
Você poderia tentar boost :: ptr_vector
http://www.boost.org /doc/libs/1_40_0/libs/ptr_container/doc/ptr_container.html
Eu não tenho certeza de explicar bem por causa do meu Inglês é pobre.
Eu acho que você deve ter para usá-lo referência ou tipo de ponteiro. porque forma é exatamente definido o que tem que fazer.
Se você usar seu código diretamente, a sua tentativa criança para copiar e fazer trabalho de forma. É por isso que não funciona sua função de override.
ponteiro de utilização ou de referência como esta.
pointer.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent* obj1;
Parent* obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { &child1, &child2 };
holder.obj1->work();
holder.obj2->work();
return 0;
}
reference.h
class Parent {
public:
virtual void work() { printf("parent is working now\n"); }
};
class Child1 {
public:
virtual void work() { printf("child1 is working now\n"); }
};
class Child2 {
public:
virtual void work() { printf("child2 is working now\n"); }
};
struct Holder {
Parent& obj1;
Parent& obj2;
};
int main() {
Child1 child1;
Child2 child2;
Holder holder = { child1, child2 };
holder.obj1.work();
holder.obj2.work();
return 0;
}
* ps: Pessoalmente eu uso a função abstrato (virtual void algo () = 0;). porque eu também esqueci sobre ele algumas vezes para que eu pegá-lo como erro de sintaxe.