2016-12-14 6 views
0

Considérons le code C++ suivant:initialiser un objet avec un constructeur de classe dérivée

#include <iostream> 

using std::cout; 

class A 
{ 
public: 
    int a; 

    A():a(0) 
    { 
     cout << "A constructor\n"; 
    } 

    virtual void f() 
    { 
     cout << "f inside A\n"; 
    } 
}; 

class C : public A 
{ 
public: 
    int c; 

    virtual void f() 
    { 
     cout << "f inside C\n"; 
    } 

    C():c(0) 
    { 
     cout << "C constructor\n"; 
    } 
}; 

int main() 
{ 
    A varA = C(); 

    cout << "Size of C class: " << sizeof(C) << "\n"; 
    cout << "Size of varA object: " << sizeof(varA) << "\n"; 

    C* varC = static_cast<C*>(&varA); 
    varC->f(); 

    cout << "varC->a is " << varC->a << "\n"; 
    cout << "varC->c is " << varC->c << "\n"; 
} 

La sortie de ce programme est:

A constructor 
C constructor 
Size of C class: 16 
Size of varA object: 8 
f inside A 
varC->a is 0 
varC->c is 1726166356 

I initialiser l'objet varA avec le constructeur de la classe C. Les constructeurs de classe A et C sont appelés, mais le varA est simplement un objet A. Je jette l'adresse de varA au type C* et j'essaie d'appeler sa fonction f(), mais il imprime la fonction f() de la classe A, donc j'en déduis que c'est utiliser le mécanisme de liaison anticipée pour l'appeler. Je pense que si j'appelle le constructeur de la classe dérivée, comme ce cas, j'obtiens le même objet si j'avais appelé le constructeur de base. Je pense que la seule différence est que les autres constructeurs sont appelés. Ma supposition est-elle exacte ou existe-t-il d'autres différences?

+0

Pourquoi vous CASTING une instance de A à C (ou C *)? Tout ce que vous avez est une instance de A. Je suppose que votre appel 'static_cast' n'est pas autorisé/non défini. –

+0

Je lance A à C pour vérifier les membres b et c. – Radioga

+1

@Dag - Le problème est qu'un 'A' n'a * aucun * membre 'b' et' c', parce que * est * un 'A'. Lors de l'attribution d'une valeur 'C', il vous suffit de [découper] (http://stackoverflow.com/questions/274626/what-is-object-slicing) la partie' A' et de rejeter le reste du 'C' objet. –

Répondre

4

Exemple classique de tranchage. A varA = C(); vous laisse avec l'objet de type statique et dynamique de A. Par conséquent, C* varC = static_cast<C*>(&varA); présente un comportement indéfini.

1

Vous pouvez stocker une classe dérivée complète dans un pointeur de classe de base, cependant:

int main() {   
    A* varA = new C(); 
    C* varC = static_cast<C*>(varA); 
    varC->f(); 

    cout << "varC->a is " << varC->a << endl; 
    cout << "varC->b is " << varC->b << endl; 
    cout << "varC->c is " << varC->c << endl; 
} // oops, forgot to delete varA/varC, memory leak!