2010-08-01 20 views
7

pregunta sobre C++ número qué mínima de los miembros de datos de definición de clase es cero¿Por qué se les permite a las clases de C++ tener miembros con cero datos?

creo que debe ser uno, es decir, puntero a la tabla virtual definido por el compilador

muchas gracias

+6

no todas las clases tienen un vtable, por lo que es irrelevante. – tenfour

+6

Tampoco los vtables tienen nada que ver con C++. Son solo una técnica de implementación común (y por lo tanto no tienen nada que ver con el lenguaje) para implementar la herencia (pero no la única). –

+4

La pregunta obvia que me preguntaría es por qué no permitir objetos de tamaño cero. El hecho de que es un tipo único tiene información que se puede usar. –

Respuesta

21

a menudo es útil para tener una clase sin miembros de datos para su uso en jerarquías de herencia.

Una clase base solo puede tener varios typedef s que se usan en varias clases. Por ejemplo, la plantilla de clase std::iterator solo tiene definidos los tipos estándar para que no necesite definirlos en cada clase de iterador.

Una clase de interfaz generalmente no tiene miembros de datos, solo funciones de miembros virtuales.

Una tabla virtual no tiene nada que ver con los miembros de datos de una clase.

+1

+1 por mencionar typedefs. –

5

Bueno, en realidad, C++ exige que todas las clases ocupen un espacio (debe poder generar un puntero a esa clase). Sin embargo, solo necesitan un puntero a un vtable, si la clase es polimórfica. No hay ninguna razón para un vtable en absoluto en una clase monomórfica.

+0

@Billy pensé que solo hay vtbl si tienes funciones virtuales? – InsertNickHere

+1

@InsertNickHere: Eso es lo que significa polimorfo. –

+0

@Billy Dident sabe que siempre hay una función virtual ya que no estoy acostumbrado a C++. – InsertNickHere

5

Estoy trabajando en una biblioteca que a veces incluso utiliza tipos que - jadeo! - ni siquiera están definidos, ¡mucho menos tienen miembros de datos!

Es decir, el tipo es incompleta, como

struct foobar; 

Esto se utiliza para crear un nombre inequívoco, nada más.

¿Para qué sirve esto? Bueno, lo usamos para crear distintos etiquetas, utilizando un tipo adicional (vacío, pero totalmente definido):

template <typename TSpec> 
struct Tag { }; 

Ahora puede crear etiquetas distintas, así:

struct TagForward_; 
typedef Tag<TagForward_> ForwardTag; 

struct TagRandomAccessible_; 
typedef Tag<TagRandomAccessible_> RandomAccessibleTag; 

Estos a su vez se puede usar para eliminar ambigüedades de sobrecargas especializadas. Muchas implementaciones STL hacen algo similar:

template <typename Iter> 
void sort(Iter begin, Iter end, RandomAccessibleTag const&) … 

En sentido estricto, la ruta indirecta a través de una plantilla común Tag clase es redundante, pero que era un truco útil para el bien de la documentación.

Todo esto solo para mostrar que un sistema de tipo (estricto, estático) se puede usar de muchas formas distintas a solo agrupar y encapsular datos.

+2

son esos nombres solo para ilustrar el ejemplo? Los nombres con guión bajo seguido de caracteres en mayúscula se reservan para la implementación :) – jalf

+0

@jalf: los nombres son sólo para ilustración. Pero tienes razón, aquí, déjame cambiarlos. –

0

Otro uso de una clase sin miembros de datos es para procesar datos de otras fuentes. Todo se pasa a la clase en tiempo de ejecución a través de punteros o referencias y la clase opera en los datos, pero no almacena nada de eso.

No había pensado en esto hasta que lo vi en una clase de UML que tomé. Tiene sus usos, pero generalmente crea clases acopladas.

0

Porque las clases no son estructuras. Su propósito, contrariamente a la creencia popular, es no para almacenar datos.

Por ejemplo, considere una clase base de validador que define un método virtual que pasa una cadena para validar y devuelve un bool.

Una instancia de un validador puede rechazar cadenas que tienen mayúsculas en ellas. Este es un ejemplo perfecto de cuándo debe usar una clase, y según la definición de lo que hace, no hay razón para tener ninguna variable miembro.

0

pregunta sobre C++ qué número mínimo de miembros de datos de definición de clase es cero

Es cero porque tiene varios casos de clases que deben tener ningún miembro:

Puede implementar clases de rasgos que contienen solo funciones estáticas por ejemplo. Estas clases son el equivalente de namespace que también se puede reconocer como un tipo. Eso significa que puede instanciar una plantilla en la clase y asegurarse de que la implementación de esa plantilla use las funciones dentro de la clase. El tamaño de dicha clase de rasgos debe ser cero.

Ejemplo:

class SingleThreadedArithmetic 
{ 
    static int Increment(int i) { return ++i; } 
    // other arithmetic operations implemented with no thread safety 
}; // no state and no virtual members -> sizeof(SingleThreadedArithmetic) == 0 

class MultiThreadedArithmetic 
{ 
    static int Increment(int i) { return InterlockedIncrement(i); } 
    // other arithmetic operations implemented with thread safety in mind 
}; // no state and no virtual members -> sizeof(MultiThreadedArithmetic) == 0 

template<class ThreadingModel> class SomeClass 
{ 
public: 
    void SomeFunction() 
    { 
     // some operations 
     ThreadingModel::Increment(i); 
     // some other operations 
    } 
}; 

typedef SomeClass<SingleThreadedArithmetic> SomeClassST; 
typedef SomeClass<MultithreadedArithmetic> SomeClassMT; 

Puede definir las categorías de clase distintos mediante la implementación de clases "etiquetar": clases que contienen ninguna interfaz o datos, pero sólo son utilizadas para diferenciar entre tipos separados "lógicas" de clases derivadas La diferenciación se puede usar en código OOP normal o en código de plantilla. Estas clases de "etiqueta" también tienen 0 tamaños. Consulte la implementación de las etiquetas de los iteradores en su biblioteca STL actual para ver un ejemplo.

Estoy seguro de que hay otros casos en los que puede usar clases de "tamaño cero".

Cuestiones relacionadas