2010-01-26 5 views
0

I have 2 classes:pointeur à l'aide à la classe de base comme paramètre de tableau

class Base 
{ 
public: 
    virtual int Foo(int n); 
     virtual void Goo() = 0; 
    virtual ~Base() ; 
}; 


class Derived : public Base 
{ 
public: 
    int Add4Bytes; 

     void Goo(); 
    int Foo(int n);  
}; 

int Test(Base* b) 
{ 
    for (int i=0;i<5;++i) 
    { 
     b->Foo(i); 
     ++b; 
    } 
    return 0; 
} 

void Test2(Base arr[]) 
{ 
    for (int i=0;i<5;++i) 
    { 
     arr[i].Foo(i); 
    } 
} 

void main 
{ 

     Base* b = new Derived[5]; 
     Test(b); 
} 

Alors, quand je vous appelle test, après la deuxième boucle il une exception viloation mémoire.

J'ai 2 questions:

  1. Quelle est la différence entre l'argument de la fonction dans le test et Test2? (Test2 ne compile pas après avoir transformé Base en pure classe abstraite).

et plus importante question

  1. Comment éviter cette exception, et comment puis-je passer un tableau de classe dérivée d'une fonction qui suppose que pour obtenir une base tableau de classe. (Je ne peux pas dire à la compilation quelle classe dérivée je vais passer la fonction)

ps - s'il vous plaît ne me dites pas de lire Meyers livre, c'est la raison exacte pour laquelle je pose cette question . :)

Merci

Répondre

3

Les tableaux ne gèrent pas bien les types polymorphes comme contenu en raison du découpage d'objet. Un élément de tableau a une taille fixe et, si vos objets dérivés ont une taille plus grande que la base, le tableau d'objets de base ne peut pas contenir les objets dérivés.

Même si le paramètre de la fonction peut se décomposer en pointeur, l'arithmétique de pointeur effectuée sur ce pointeur sera basée sur la taille de l'élément du type de tableau.

Pour gérer les tableaux de types polymorphes, vous devez ajouter un autre niveau d'indirection et gérer les tableaux (ou tout autre conteneur) de pointeurs vers les objets.

Test2 ne compile pas après je me suis tourné de base en classe abstraite pur

Vous ne pouvez pas avoir des tableaux de types abstraits parce que vous ne pouvez pas avoir des instances de types abstraits (uniquement des pointeurs ou des références à leur).

4

Il n'y a pas de différence entre les types de paramètres, les paramètres du tableau sont ajustés à des pointeurs dans les déclarations de fonction.

Alors que vous pouvez convertir un pointeur vers Derived à un pointeur vers Base, vous ne pouvez pas traiter un tableau de Derived comme un tableau de Base, ils ne sont pas les types connexes. Cela est dû au fait que dans un tableau de Derived, la classe Base est un sous-objet de Derived et ne fait pas partie d'un tableau de Base. Lorsque vous exécutez l'arithmétique de pointeur comme si elle faisait partie d'un tableau de Base vous obtenez un comportement indéfini, vous êtes susceptible de construire un pointeur Base qui ne pointe pas exactement au début d'un objet Base.

1

Vos Test étapes de fonction par tableau de Base objets, à savoir la foulée est sizeof(Base), alors qu'il doit être sizeof(Derived). Vous voulez probablement le déclarer comme:

int Test(const std::vector<Base*>&);
Questions connexes