Utiliser une classe abstraite en C ++
Je suis en train d'utiliser une classe abstraite lors du passage d'un objet étendu comme un paramètre à une fonction, mais mes tentatives ont jusqu'à présent conduit à certaines des erreurs du compilateur.
J'ai quelques indices quant à ce que le problème est, je ne suis évidemment pas autorisé à instancier une classe abstraite, et je crois qu'une partie du code dans Maclasse est en train de faire cela, même si ce n'est pas mon intention. Certaines recherches ont suggéré que je doit faire référence à l'objet en tant que pointeur pour obtenir ce que je veux, mais mes tentatives ont jusqu'à présent échoué et je ne suis même pas sûr que c'est la réponse (d'où ma demande ici).
Je vais présenter maintenant que je suis plus familier avec Java qu'en C++, et je suis sûr qu'une partie de mon problème est à cause de cela.
Voici un exemple de ce que je suis en train de faire dans mon programme:
class A {
public:
virtual void action() = 0;
};
class B : public A {
public:
B() {}
void action() {
//Do stuff
}
};
class MyClass {
public:
void setInstance(A newInstance) {
instance = newInstance;
}
void doSomething() {
instance.action();
}
private:
A instance;
};
int main(int argc, char** argv) {
MyClass c;
B myInstance;
c.setInstance(myInstance);
c.doSomething();
return 0;
}
Cet exemple génère la même erreur de compilation que je suis arriver dans mon programme:
sean@SEAN-PC:~/Desktop$ gcc -o test test.cpp
test.cpp:20: error: cannot declare parameter ‘newInstance’ to be of abstract type ‘A’
test.cpp:2: note: because the following virtual functions are pure within ‘A’:
test.cpp:4: note: virtual void A::action()
test.cpp:30: error: cannot declare field ‘MyClass::instance’ to be of abstract type ‘A’
test.cpp:2: note: since type ‘A’ has pure virtual functions
test.cpp: In function ‘int main(int, char**)’:
test.cpp:36: error: cannot allocate an object of abstract type ‘A’
test.cpp:2: note: since type ‘A’ has pure virtual functions
Mise à jour
Merci pour les commentaires tout le monde.
Depuis, j'ai changé "Maclasse::instance pour contenir un pointeur de type A, mais maintenant, je reçois quelques bizarres les erreurs liées à la vtable:
sean@SEAN-PC:~/Desktop$ gcc -o test test.cpp
/tmp/ccoEdRxq.o:(.rodata._ZTI1B[typeinfo for B]+0x0): undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
/tmp/ccoEdRxq.o:(.rodata._ZTI1A[typeinfo for A]+0x0): undefined reference to `vtable for __cxxabiv1::__class_type_info'
/tmp/ccoEdRxq.o:(.rodata._ZTV1A[vtable for A]+0x8): undefined reference to `__cxa_pure_virtual'
collect2: ld returned 1 exit status
Mon code modifié est comme suit (A et B n'ont pas été modifiés):
class MyClass {
public:
void setInstance(A* newInstance) {
instance = newInstance;
}
void doSomething() {
instance->action();
}
private:
A* instance;
};
int main(int argc, char** argv) {
MyClass c;
B myInstance;
c.setInstance(&myInstance);
c.doSomething();
return 0;
}
source d'informationauteur seanhodges
Vous devez vous connecter pour publier un commentaire.
Votre problème est que vous devez les accepter une référence dans votre fonction. La raison en est qu'une référence ne fait pas de copie de l'argument passé. Si cependant vous acceptez un
A
- au lieu d'une référenceA&
- vous alors fait copier l'argument passé en paramètre de l'objet, et ce que vous obtenez est un objet de typeA
- mais qui n'est pas autorisé!Et alors vous devrez modifier le membre de votre classe à un pointeur. Il ne peut pas être une référence, car
setInstance
changera quoi il fait référence - une référence peut uniquement faire référence à un objet, pendant toute la durée de vie, tandis que un pointeur peut être réglé sur le point de faire des choses différentes mais en réaffectant une adresse différente. Les parties restantes ressembler à ceci puisNotez également que vous devez compiler des programmes C++ à l'aide de
g++
car il en outre des liens de la norme C++ de la bibliothèque de votre codeCe que vous faites travailler dans Java parce que la déclaration d'un paramètre ou d'une variable membre de type "A" signifie bien un "pointeur vers une". En C++, vous avez réellement besoin d'être explicite à ce sujet depuis qu'ils sont deux choses différentes:
Et dans la déclaration:
Votre problème est maintenant un lien.
Pour un programme C++, C++ standard library a ajouté:
gcc-o test -lstdc++ test.cpp
Je crois que c'est ce que vous essayez de faire. Il démontre le polymorphisme en fait, l'impression de quelque chose selon que la poignée de points de classe à une instance de B ou C. les Autres sont correctes que vous auriez probablement souhaitez également un destructeur virtuel.
Cette compile avec g++ test.cpp -o Test
Vous devez stocker Un pointeur.
Edit: j'ai écrit "de référence" avant de. Il y a une différence en C++.
Vous n'avez pas à utiliser des pointeurs si vous démissionnez de l'incubateur et l'utilisation d'un constructeur. C'est l'une des caractéristiques les plus importantes dans C++: la base des initialiseurs dans les constructeurs permettent souvent d'éviter d'utiliser des pointeurs.
J'ai eu ce problème en incluant
parent.h
avantiostream
:mal:
droite:
Johannes Schaub - litb est correct.
En C++, une classe Abstraite ne peut pas être utilisé en tant que fonctions' param ou le type de retour. On ne peut pas instancier un objet abstrait.
Donc besoin d'utiliser & ou *.
Vous devez utiliser un pointeur sur Un membre de MyClass.
si vous ne le faites pas, MyClass constructeur va essayer d'instancier Un objet (comme il le ferait pour n'importe quel membre de l'objet), qui n'est pas possible depuis Un est abstrait.
Quand vous dites
vous permettra de créer un nouvel objet de type A. Mais vous l'avez déjà dit que isa une classe abstraite, de sorte que vous ne pouvez pas. Vous avez besoin d'utiliser un pointeur, comme plusieurs otherrs ont indiqué, ou de faire Un non-abstraite.
Dmitry est correct, vous devez utiliser -lstdc++ si vous utilisez gcc, mais encore mieux, c'est d'utiliser
g++
à la place. (Même syntaxe).Aussi, vous remarque (je suppose que si vous ajoutez -Mur) que vous obtenez un avertissement que votre classe avec des fonctions virtuelles est sans un destructeur, donc, une bonne idée est d'ajouter un (virtuel) destructeur de A ainsi.