2010-10-28 13 views
29

Lo siento, esto puede parecer simple, pero alguien me preguntó esto, y no lo sé con certeza.¿Cuántos métodos predeterminados tiene una clase?

¿Una clase vacía de C++ viene con qué funciones?

Constructor, Copy Constructor, Assignment, Destructor?

¿Eso es todo? ¿O hay más?

+0

Me lo han preguntado en 3 entrevistas ahora. – Vbp

Respuesta

41

En C++ 03 hay 4:

  • constructor por defecto: Declarado solo si ningún constructor definido por el usuario es declarado. Definido cuando se usa

  • Copiar constructor - declarado solo si el usuario no ha declarado uno. Definido si se utiliza

  • operador Copy-asignación mismo que el anterior

  • Destructor mismo que el anterior

En C++ 11 hay dos más:

  • Mover constructor
  • Move-operador de asignación

También es posible que el compilador no será capaz de generar algunos de ellos. Por ejemplo, si la clase contiene, por ejemplo, una referencia (o cualquier otra cosa que no pueda copiarse), el compilador no podrá generar un operador de asignación de copias para usted.For more information read this

+5

En realidad, está en el aire si el constructor de movimientos y el operador de asignación de movimiento se declararán implícitamente en C++ 0x; hay artículos de Dave Abrahams y Bjarne Stroustrup en el correo WG21 de octubre sobre este tema. Existe la preocupación de que su declaración implícita pueda romper el código heredado. –

+0

Creo que tener una referencia como variable miembro evitaría la generación del operador de asignación predeterminado, no causaría problemas con el constructor de copia. –

+0

@Ben: Sí, tienes razón, arreglando. Gracias :) –

0

¿Eso es todo?

Sí thats it.

compilador genera por defecto

  • Un constructor por defecto
  • Un constructor de copia
  • Un operador de asignación de copia
  • Un destructor

para una clase

Puede ver lafa ULT constructor, el constructor de copia y el operador de asignación que se genera por omisión cuando se utiliza la opción de -ast-dump Clang

[email protected] ~ $ cat empty.cpp && clang++ -cc1 -ast-dump empty.cpp 
class empty 
{}; 

int main() 
{ 
    empty e; 
    empty e2 = e; 
    { 
    empty e3; 
    e3 = e; 
    } 

} 
typedef char *__builtin_va_list; 
class empty { 
    class empty; 
    inline empty() throw(); //default c-tor 
    //copy c-tor 
    inline empty(empty const &) throw() (CompoundStmt 0xa0b1050 <empty.cpp:1:7>) 

    //assignment operator 
    inline empty &operator=(empty const &) throw() (CompoundStmt 0xa0b1590 <empty.cpp:1:7> 
    (ReturnStmt 0xa0b1578 <col:7> 
    (UnaryOperator 0xa0b1558 <col:7> 'class empty' prefix '*' 
     (CXXThisExpr 0xa0b1538 <col:7> 'class empty *' this)))) 


}; 
+0

No creo que el destructor realmente se haya generado. – Andrey

+4

Es, el destructor predeterminado solo llama a los destructores en todos los miembros. Si no hiciera esto, todos los miembros se fugarían cada vez que el objeto principal fuera destruido. – AshleysBrain

+1

@ Ashley En realidad, no, el destructor no llama nada. Esto se hace fuera del destructor. –

12

Si defino la siguiente clase

class X 
{}; 

El compilador definirá los métodos siguientes:

X::X() {}     // Default constructor. It takes zero arguments (hence default). 
X::~X() {}     // Destructor 
X::X(X const& rhs) {};  // Copy constructor 
X& operator=(X const& rhs) 
{return *this;}    // Assignment operator. 

Nota:
El constructor por defecto no se construye si se ha definido CUALQUIER constructor .
Los otros métodos no se crean si el usuario define una alternativa.

Lo que es un poco más interesante es la implementación predeterminada cuando tenemos miembros y una base:

class Y: public X 
{ 
    int a;  // POD data 
    int* b;  // POD (that also happens to be a pointer) 
    Z  z;  // A class 
}; 

// Note: There are two variants of the default constructor. 
//  Both are used depending on context when the compiler defined version 
//  of the default constructor is used. 
// 
//  One does `default initialization` 
//  One does `zero initialization` 

// Objects are zero initialized when 
// They are 'static storage duration' 
// **OR** You use the braces when using the default constructor 
Y::Y()  // Zero initializer 
    : X() // Zero initializer 
    , a(0) 
    , b(0) 
    , z() // Zero initializer of Z called. 
{} 

// Objects are default initialized when 
// They are 'automatic storage duration' 
// **AND** don't use the braces when using the default constructor 
Y::Y() 
    :X // Not legal syntax trying to portray default initialization of X (base class) 
    //,a // POD: uninitialized. 
    //,b // POD: uninitialized. 
    ,z // Not legal syntax trying to portray default initialization of z (member) 
{} 
// 
// Note: It is actually hard to correctly zero initialize a 'automatic storage duration' 
//  variable (because of the parsing problems it tends to end up a a function 
//  declaration). Thus in a function context member variables can have indeterminate 
//  values because of default initialization. Thus it is always good practice to 
//  to initialize all members of your class during construction (preferably in the 
//  initialization list). 
// 
// Note: This was defined this way so that the C++ is backward compatible with C. 
//  And obeys the rule of don't do more than you need too (because we want the C++ 
//  code to be as fast and efficient as possible. 


Y::Y(Y const& rhs) 
    :X(rhs)    // Copy construct the base 
    ,a(rhs.a)   // Copy construct each member using the copy constructor. 
    ,b(rhs.b)   // NOTE: The order is explicitly defined 
    ,z(rhs.z)   //  as the order of declaration in the class. 
{} 

Y& operator=(Y const& rhs) 
{ 
    X::operator=(rhs); // Use base assignment operator 
    a = rhs.a;   // Use the assignment operator on each member. 
    b = rhs.b;   // NOTE: The order is explicitly defined 
    z = rhs.z;   //  as the order of declaration in the class. 
    return(*this); 
} 

Y::~Y() 
{ 
    Your Code first 
} 
// Not legal code. Trying to show what happens. 
    : ~z() 
    , ~b() // Does nothing for pointers. 
    , ~a() // Does nothing for POD types 
    , ~X() ; // Base class destructed last. 
+1

La definición de operador de asignación es defectuosa porque no tiene una declaración de devolución dentro de una función no nula. –

+0

Y el operador de asignación devuelve referencia constante, valor o vacío. –

+0

@Let_Me_Be: No. Devuelve una referencia. Intenta usar un objeto después de la asignación. –

0

métodos predeterminados asignados por el compilador para una clase vacía:

http://cplusplusinterviews.blogspot.sg/2015/04/compiler-default-methods.html

+1

Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace de referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. Por favor, eche un vistazo aquí: [¿Por qué y cómo se eliminan algunas respuestas?] (Http://stackoverflow.com/help/deleted-answers) – bummi

3

Sólo para ampliar en Armen Tsirunyan answer aquí están las firmas para los métodos:

// C++03 
MyClass();          // Default constructor 
MyClass(const MyClass& other);     // Copy constructor 
MyClass& operator=(const MyClass& other);  // Copy assignment operator 
~MyClass();         // Destructor 

// C++11 adds two more 
MyClass(MyClass&& other) noexcept;    // Move constructor 
MyClass& operator=(MyClass&& other) noexcept; // Move assignment operator 
Cuestiones relacionadas