2010-10-27 15 views
16

¿Cuáles podrían ser las posibles ventajas/usos de tener una clase vacía?Ventajas de una clase vacía en C++

P.S: Esta pregunta puede sonar trivial para algunos de ustedes, pero es sólo para fines de aprendizaje y no tiene importancia práctica. FYI Google no ayudó.

+0

Hay un par de situaciones en las que puede ser útil; ¿Puedes dar un ejemplo para que podamos tener algún contexto? – Nate

+1

Vacío como en ningún miembro o función; o vacío como usar el patrón Objeto nulo? – SwDevMan81

+1

¿vio este enlace http://www.cplusplus.com/forum/general/8370/? – bjskishore123

Respuesta

17

Un uso sería en la programación de plantillas (meta-): por ejemplo, iterator tags se implementan como clases vacías. El único propósito aquí es pasar la información en tiempo de compilación para que pueda verificar, si un iterador pasó a, p. una función de plantilla cumple con requisitos específicos.

Ejemplo:

Esto es realmente simplificada, sólo para ge una idea. Aquí el propósito de la clase de etiqueta es para decidir, que la aplicación de un algoritmo de empleo:

class forward_iterator_tag {}; 
class random_access_iterator_tag {}; 

class MySimpleForwardIterator { 
public: 
    typedef typename forward_iterator_tag tag; 
    // ... 
}; 

class MySimpleRandomIterator { 
public: 
    typedef typename random_access_iterator_tag tag; 
    // ... 
}; 

template<class iterator, class tag> 
void myfunc_int(iterator it, tag t) { 
    // general implementation of myfunc 
} 

template<class iterator> 
void myfunc_int<iterator, forward_iterator_tag>(iterator it) { 
    // Implementation for forward iterators 
} 

template<class iterator> 
void myfunc_int<iterator, random_access_iterator_tag>(iterator it) { 
    // Implementation for random access iterators 
} 

template<class iterator> 
void myfunc(iterator it) { 
    myfunc_int<iterator, typename iterator::tag>(it); 
} 

(espero que me dieron ese derecho, que ha pasado un tiempo desde que utiliza este ...)

Con este código, puede llamar al myfunc en un iterador arbitrario y dejar que el compilador elija la implementación correcta según el tipo de iterador (es decir, la etiqueta).

+0

¿Podrías por favor explicar con la ayuda de fragmentos de código? – Ron

+1

vistazo a la aplicación de algunas iterador STL, usted debe tener el código en cualquier compilador –

1

Una clase vacía podría usarse como un "token" que define algo único; en ciertos patrones, desea una representación independiente de la implementación de una instancia única, que no tiene ningún valor para el desarrollador que no sea su singularidad. Un ejemplo es la Unidad de trabajo; Es posible que no le importe un poco lo que sucede dentro de su artista intérprete o ejecutante, pero desea decirle a ese intérprete que las tareas que le está diciendo que realice son parte de un conjunto atómico. Una clase vacía que representa la Unidad de Trabajo para el mundo exterior puede ser perfecta en este caso; casi cualquier cosa que un objeto de Unidad de trabajo pueda almacenar o encapsular (encapsulando una transacción DB, exponiendo comportamientos Commit/Rollback) comenzaría a vincularlo a una implementación particular, pero una referencia de objeto es útil para proporcionar una referencia única pero reproducible y pasable al atómico conjunto de tareas.

0

clases "vacías" significa las clases que no tienen miembros de datos? Por lo general, declaran typedefs o funciones de miembro, y puede ampliarlas con sus propias clases.

+0

Cuál es exactamente su punto? – Ron

+0

Tomado de este artículo: http://www.cantrip.org/emptyopt.html – SwDevMan81

+0

(Inglés no es mi lengua materna) pseudocódigo clase Shape { zona de doble virtual(); } Círculo clase extender Forma { doble zona() } clase Square extender Forma { doble zona() } –

0

Here es un enlace interesante con respuestas a por qué está permitido. Puede encontrar esto útil para encontrar situaciones en las que podría ser útil.

+0

El artículo que menciona habla sobre miembros * no * de datos. Las clases que tienen solo miembros de función son ampliamente utilizadas (por ejemplo, para la definición de interfaz). Creo que el OP significaba clases vacías sin * any * miembros. – MartinStettner

+0

@MartinStettner - La publicación que tengo en esta pregunta se refiere a por qué está permitido. El otro artículo que publiqué fue para mostrar de dónde venía la respuesta de Javi. Al leer el artículo verá la respuesta textualmente en el artículo. No estaba publicando como una respuesta. – SwDevMan81

1

Puede usarlo como un marcador de posición para fines de comprobación o como habilitador de funciones especiales. Por ejemplo, en Java existe la interfaz "vacía" Serializable utilizada para especificar si una clase es serializable.

2

En el STL, Biblioteca de plantillas estándar del C++, por ejemplo, tiene

template<class _Arg, 
class _Result> 
struct unary_function 
    { // base class for unary functions 
typedef _Arg argument_type; 
typedef _Result result_type; 
    }; 

Cuando se define un funtor, que pueden heredar unary_function, y entonces usted tiene el typedef define de forma automática a su disposición.

5

Lo siguiente se puede utilizar para tener un boost::variant que puede contener un valor NULL (SQL) por ejemplo.

class Null { }; 

typedef boost::variant<Null, std::string, int> Value; 

para hacerla más cosas útiles como operator== y operator<< son muy útiles.Por ejemplo:

std::ostream& operator<<(std::ostream &lhs, const Null &rhs) 
{ 
    lhs << "*NULL*"; 
    return lhs; 
} 

int main() 
{ 
    Variant v("hello"); 
    std::cout << v << std::endl; 
    v = Null(); 
    std::cout << v << std::endl; 
    ... 
} 

dará:

hello 
*NULL* 
0

Como han dicho otros, a menudo una clase vacía (o estructura) se utiliza un marcador de posición, un diferenciador, un contador, etc.

Por ejemplo, mucha gente no sabe que hay versiones "nuevas" del operador nuevo. La sintaxis para invocar nothrow nueva es:

p = new(std::nothrow) Bar; 

y std :: nothrow se define simplemente como

struct nothrow_t {}; //defined in namespace std 
0

La respuesta por MartinStettner está bien, aunque sólo para destacar un punto importante: el concepto de etiquetas de iterador o para el caso, cualquier etiqueta en C++, no es estrictamente dependiente de las clases vacías. Las etiquetas C++, si los escritores STL hubiesen querido, bien podrían haber sido clases no vacías; eso debería funcionar, pero luego no agregará ningún valor adicional; al menos para las acrobacias en tiempo de compilación para las que normalmente está destinado.