2009-04-30 15 views
6

Ahora estoy usando std :: pair para representar un punto 2d en C++. Sin embargo, estoy consiguiendo molesto con tener que escribirHaciendo una clase de punto en C++

typedef std::pair<double, double> Point; 

Point difference = Point(p2.first - p1.first, 
         p2.second - p1.second); 

en lugar de ser capaz de sobrecargar el operador + y del operador.

Por lo tanto, mi pregunta es, hacer que mi clase Point, debería

  • públicamente derivar de std :: pair y añadir mis propias funciones miembro? Esto es bueno porque todo mi código puede permanecer igual. No voy a hacer nada como std::pair<double, double>* p = new Point;, así que no tengo que preocuparme por cosas como los destructores virtuales.
  • Tira mi propia clase de punto, que es molesto ya que estoy duplicando la funcionalidad de std :: pair, sin embargo, estoy "haciéndolo de la manera pura".
  • Realice especializaciones de plantilla de operator + y operator- for std :: pair, que sin duda no recuerdo si van en archivos de fuente o de encabezado.

Supongo que es un tema de debate, me gustaría hacer # 1, pero no sé si es una mala idea ya que he oído que heredar de STL es un no-no.

+3

FYI - la razón por la que heredar de la STL es un no-no es que no tiene un destructor virtual. Entonces, si eliminaste tu propia clase mediante un puntero al tipo de base STL, no se invocaría tu destructor. – JohnMcG

+0

Dije que no haría eso en la pregunta. – rlbond

+0

No pensé que lo haría; solo pensé que sería útil dar la razón por la cual. – JohnMcG

Respuesta

14

Puede rodar su propia clase de punto, pero use std :: pair internamente para almacenar los datos. Esto evita la herencia del problema de STL, pero aún usa la funcionalidad de std :: pair.

+1

+1. Si lees Code Complete, sugiere esta práctica exacta: Si [la clase Point] * es * a [std :: pair], entonces hereda. De lo contrario, [std :: pair] debería almacenarse como un miembro privado, y [Point] debería definir su propia interfaz. "point.first" no tiene sentido; point.x hace. – ojrac

+0

Probablemente de ahí he sacado la idea. ¡Ese libro es genial! –

+0

Entiendo por qué heredar de 'stl :: pair' no es bueno; pero ¿por qué incluso usar 'stl :: pair' en primer lugar? ¿Qué características de 'stl :: pair' son relevantes para' Point'? Tal vez me falta algo obvio, pero ordenar, 'swap',' get', varios constructores, todos parecen ser irrelevantes para 'Point'. – max

1

Otra opción podría ser hacer su propia clase Point, y tener su clase "propia" un std :: pair que represente las coordenadas del punto.

Muchas veces una relación "HAS A" (composición) es preferible a una relación "IS A" (herencia).

1

Creo que las "Mejores prácticas" dirían para rodar su propia clase de puntos. De esta manera, puedes hacer 3D mucho más fácil en el futuro.

+0

no hay absolutamente ninguna necesidad de 3d. Es para un juego. Un 2do juego. – rlbond

+0

2 dimensiones deberían ser suficientes para cualquiera !!! Lo siento por eso –

1

Herencia privada alias herencia de implementación, es su amigo.

Esto sigue lógicamente: un punto NO es una std :: pair, no desea tener una conversión pública de conversión de Point a std :: pair, pero sí quiere usar las internas de std :: pair .

La otra posibilidad es una relación o composición has-a: cada punto tiene un privbate std :: pair que usa internamente.

De hecho, no hay mucha diferencia entre la composición y la herencia privada, excepto que en este último puede forzar un up-cast a std :: pair en una función miembro de Point.

0

Lanza tu propia clase de punto. Esto le permitirá hacer cualquier cantidad de cosas en el futuro. Específicamente, he resuelto este tipo de problema anteriormente, y lo que he encontrado útil es definir mi propia estructura de puntos y crear una clase de puntos que herede de ella.

Revelación completa: No me gusta mucho el STL.

2

Mejor que rodar el suyo: obtenga una biblioteca Vector/Point gratuita existente. Una recomendación: la adjunta al Essential Math for Games Programmers. Puede usar cualquier biblioteca que encuentre como punto de partida, luego optimizar/especializar/modificar desde allí.

2

Estaría a favor de crear su propia clase de punto y usar herencia privada o composición si desea emplear la funcionalidad de std :: pair. El problema con typedef (como estoy seguro de que sabe) es que cualquier función que escriba que tome un punto también podrá ser utilizada por cualquier elemento representado como std :: pair < double, double >, que puede no ser válido.

Con esto en mente, existe otra opción de sólo la creación de algunas de las funciones del constructor libres como

Point addPoints(const Point& p1, const Point& p2); 
Point diffPoints(const Point& p1, const Point& p2); 

(los nombres de función podría ser mejor).

0

No herede públicamente de std :: pair porque std :: pair tiene un operador < pero su punto no debería tener.