2010-07-07 13 views
29

tengo una clase que se parece a:C++: ¿Inicializar un puntero de miembro a nulo?

class Foo 
{ 
public: 
    Foo(); 
    virtual ~Foo(); 

private: 
    Odp* bar; 
}; 

Deseo inicializar bar a NULL. ¿Es esta la mejor manera de hacerlo?

Foo::Foo() : bar(NULL) 
{ 
} 

Además, ¿es necesario que el destructor sea virtual? (Si esto es cierto, entonces debe ser el constructor virtual, así?)

+1

Posiblemente mejor es solo 'Foo :: Foo(): bar() {}' (Nota, no 'NULL'.) Lo mejor es no tener el puntero, sin embargo. – GManNickG

+2

¿Por qué es eso mejor? ¿Está el 'NULL' implícito? –

+2

"¿Por qué es eso mejor?" No necesita incluir un archivo de encabezado para la definición de 'NULL' (que de todos modos es' 0'). "¿Está implícito el' NULL'? " Sí. 'bar()' es una inicialización de valor; en el caso de un puntero, lo inicializa a nulo. –

Respuesta

39

Deseo inicializar bar a NULL. ¿Es esta la mejor manera de hacerlo?

Es el correcto manera. Entonces sí.

Además, ¿es necesario que el destructor sea virtual?

No. El destructor sólo necesita ser virtual si va a heredar de la clase Foo y va a utilizar un puntero Foo eliminar esas clases derivadas (aunque como regla general, debe ser virtual si hay otros miembros virtuales).

(Si esto es cierto, entonces debe ser el constructor virtual, así?)

No. constructores ni necesidad de ser virtual, ni puedo ellos.

+0

+1 Buena respuesta concisa. Inicializo miembros no constantes en el cuerpo del ctor. Hace que leer el código sea un poco más claro (en relación con el tipo de calificador de miembro). – Poni

+14

@Poni: No, no, los reasignas. Todos los miembros se inicializan al comienzo del cuerpo constructor. Es por eso que generalmente se considera una mala práctica "inicializar" las cosas allí. Claro, con los tipos primitivos no pierdes nada, pero no todos los tipos son primitivos, y es mejor ser consistente. "Claro" vendrá a medida que los use más y se acostumbre a la sintaxis. – GManNickG

+0

MyClass :: MyClass(): m_const_var (VALUE) {this-> m_non_const_var = OTHER_VALUE} <<<< no obtuvo exactamente lo que dijo GMan, pero esto es lo que quería decir.Entonces, ¿estás diciendo que esto está mal? ¿Estás diciendo que deberíamos incluir la inicialización de m_non_const_var en el área de inicialización de los miembros del ctor al igual que haciendo con m_const_var? – Poni

10
  1. Sí, la lista de inicialización es lo mejor.

  2. Quizás. El destructor debe ser virtual si pretendes tener otras funciones virtuales en la clase, o si pretendes heredar la clase (aunque generalmente esas cosas van juntas).

  3. No. No es posible tener un constructor virtual en C++. (Lo que sería una cosa tan siquiera significa?)

La naturaleza de su pregunta me sugiere que no entiendo muy bien lo que hace la palabra clave virtual, o lo que es es, y usted son sólo copiando algo que vio en otro lugar o en un tutorial. Lo mejor es comprender el propósito de todos del código que está escribiendo. Aquí podría ser un punto de partida: http://www.parashift.com/c++-faq-lite/virtual-functions.html

+0

Solo un FYI en respuesta a "¿qué significaría eso?": Algunas personas pueden usar el término "constructor virtual" para el patrón de fábrica (http://www2.research.att.com/~bs/bs_faq2. html # virtual-ctor). –

+0

+1 para el enlace. Es bastante útil. –

2

1, sí

2, sólo si quieres que alguien sea capaz de derivar de su clase y utilizar un puntero a la clase base - pero hacer que el dtor virtual de todos modos

3, no, no puede tener un ctor virtual (o todos ctors son virtuales supongo?)

+4

"todos los ctors son virtuales" - no, la decisión sobre qué constructor llamar se realiza en tiempo de compilación. "Virtual" implicaría una decisión de tiempo de ejecución. –

3

Otra opción que podría considerar es el uso de una clase puntero inteligente (como boost::scoped_ptr, boost::shared_ptr o de C++ 0x unique_ptr) en lugar de un puntero en bruto. El constructor del puntero inteligente se asegurará de que se inicialice en algo parecido a NULL si no necesita alguna otra inicialización explícita. El puntero inteligente también asegurará que el objeto apuntado se destruya.

Solo tiene que decidir qué tipo de política de punto inteligente es apropiada para el artículo y elegirlo en consecuencia (incluso auto_ptr podría ser mejor que un puntero sin formato, siempre que sepa las diversas dificultades).

9

Existen cuatro formas distintas. ¿Cuál es la mejor depende de usted

Foo::Foo() : bar() // value initialization 
{ 
} 

Foo::Foo() : bar(0) // direct null pointer constant 
{ 
} 

Foo::Foo() : bar(NULL) // null pointer constant by macro 
{ 
} 

Foo::Foo() : bar(nullptr) // pointer literal of type std::nullptr_t 
{ 
} 
+0

y ahora 'Foo :: Foo(): bar (nullptr) {}' – nurettin

0

funciones virtuales son para determinar qué función de la clase (que se define en tanto base y clase derivada) debe ser llamado durante la ejecución. Pero cuando se crea un objeto, el compilador sabe a qué constructor se debe llamar. por ej. cuando se crea el objeto base, el constructor base se llama e igual para la clase derivada. Por lo tanto, hacer que el constructor sea virtual no tiene sentido. Pero una vez cuando el puntero del objeto de la clase base apunta al objeto de clase derivado, y luego se llama al destructor, el compilador se confunde con el destructor (derivado o derivado) que se llama solo se puede resolver usando la tabla de búsqueda vtable y, por lo tanto, el destructor debe ser virtual.

Cuestiones relacionadas