2010-07-12 13 views
5

Tengo dos clases, y punto de píxel:C++ herencia/plantilla de preguntas

class point { 
    public: 
     point(int x, int y) : x(x), y(y) { }; 
    private: 
     int x, y; 
} 

template <class T> 
class pixel : public point { 
    public: 
     pixel(int x, int y, T val) : point(x, y), val(val) { }; 
    private: 
     T val; 
} 

Ahora aquí es mi problema. Quiero hacer una clase contenedora (llamémosle coll) que tenga un vector privado de puntos o píxeles. Si una instancia de coll contiene píxeles, quiero que tenga un método para Array(), que convierte su vector de píxeles a una matriz de T que representa el contenido del vector.

Iba a hacer esto con la herencia: es decir, podría hacer un coll de clase base que contenga un vector de puntos y una clase derivada que contenga el método extra, pero luego parece que tengo problemas ya que pixel es plantilla de clase.

¿Alguien tiene alguna sugerencia? ¿Podría hacer esto de alguna manera haciendo de coll una plantilla de clase?

+0

Creo que 'coll' también debería ser una clase de plantilla. Entonces puedes especializar parcialmente 'coll' para puntos y para píxeles. – Philipp

+0

¿Es el píxel un conjunto de coordenadas (es decir, hereda el "punto") o tiene coordenadas (es decir, contiene una instancia de punto)? – Patrick

+0

Hereda del punto. – amc

Respuesta

3

Pregunta: ¿Quiere decir que el vector privado contiene tanto puntos como píxeles al mismo tiempo, o solo uno u otro?

Pregunta: Si solo uno u otro, ¿quieres mezclar píxeles con diferentes parámetros de plantilla en el mismo vector privado?

Suponiendo que es sólo punto o píxel en el vector privada, y que los píxeles en el vector privada, todos tienen el mismo parámetro de plantilla, se podría hacer algo como esto:

template < class T > class CollectionBase 
{ 
    //common interface here 
    protected: 
    std::vector<T> coll_vec; 
}; 

class PointCollection : public CollectionBase<Point> 
{ 
    public: 
    ... 
}; 

template< class T> PixelCollection : public CollectionBase<Pixel<T> > 
{ 
    public: 
    Pixel<T>* toArray(); 

    ... 

}; 
+0

Respuesta: solo uno o el otro. Respuesta: solo píxeles con el mismo parámetro de plantilla. Esta solución parece bastante buena, pero mis colecciones tendrán muchas de las mismas funcionalidades: ¿no requerirá mucha duplicación del mismo código ya que CollectionBase no tendrá acceso a los contenedores? – amc

+0

@amc respuesta actualizada para evitar la duplicación de código. Hace un poco de PointCollection un poco redundante, pero esto evitará que la mayoría de los lanzamientos de PixelCollection a PointCollection y viceversa. Si tiene la intención de permitir que se emitan entre sí, entonces podría colapsar CollectionBase y PointCollection juntos en una sola clase. – diverscuba23

+0

IMPRESIONANTE, esto es exactamente lo que quería. Supongo que no me di cuenta de que podías subclasificar una clase de plantilla. ¡Gracias! – amc

1

Si desea compruebe si un objeto point es también un tipo de pixel<T>, entonces simplemente puede ver si dynamic_cast devuelve NULL. Para hacer esto, point tendrá que ser polimórfico, por lo que debe agregarle un destructor virtual.

He aquí un ejemplo:

point x(0, 0); 
pixel<int> y(0, 0, 0); 
point *pX = &x; 
point *pY = &y; 
if(dynamic_cast<pixel<int> *> (pX) != NULL) { 
    std::cout << "x is a pixel<int>."; 
} 
if(dynamic_cast<pixel<int> *> (pY) != NULL) { 
    std::cout << "y is a pixel<int>."; 
} 

La salida es la siguiente:

y es un int píxeles <>.

Usted podría utilizar este código en tu clase coll para comprobar si cada elemento de una vector<point *> es un punto o un píxel. Sin embargo, con el fin de hacerlo, usted necesita saber qué especialización de píxel está siendo almacenada (es decir, se trata de una pixel<int> o una pixel<float>?)

Puede ser más fácil de hacer coll una plantilla de clase en su lugar.

1

Si collection trata point sy pixel s son en su mayoría iguales y solo contiene uno u otro, tiene sentido convertirlo en una clase de plantilla.
En cuanto to_array sin embargo, podría ser más simple para que sea una función libre en su lugar:

template<class T> struct collection { 
    std::vector<point<T> > data_; 
    // ... 
}; 

template<class T> 
void to_array(const collection<point<T> >& in, point<T>* out) { 
    // ... 
} 

Tenga en cuenta que usted tendría que proporcionar una interfaz pública para el acceso de lectura a los datos, sin embargo, o al menos conceder selectivamente to_array() acceso .