J'essaie de faire une tâche relativement simple ici et je ne suis pas sûr de savoir comment y aller.
J'ai deux classes d'intérêt Bit pertinent de la Bit pertinent de parent.h strong>: p> Ce que je voudrais réaliser est pour le ci-dessus, moi-même désigne le peu que je ne sais pas comment coder. P> Alors quand je cours Ceci: P> parent code> et enfant code>. Les deux sont un cas particulier de la classe humaine. Je les crée en tant que telle. P> addchild () code>. Ce qu'il fait est simplement ajoute un enfant à un vecteur d'enfants à l'intérieur d'un objet parent. P> addchild ( ) code> fonction pour ajouter simultanément un parent à l'enfant aussi. C'est-à-dire que faire quelque chose comme: p> In member function 'void Parent::addChild(Child&)':
invalid use of incomplete type 'class Child'
child.parents.emplace_back(*this);
error: forward declaration of 'class Child'
class Child;
4 Réponses :
Vous avez un problème lorsque vous utilisez Void AddChild (Human Ahuman) sans & vous devez faire du vide AddChild (Human & Ahuman) Si vous avez changé pour enregistrer dans l'objet sans et vous copiez 2 fois les objets 1 dans l'appel fonctionner et un lorsque vous insérez à AddChild (Child1); Moi-même peut être ceci mais vous devez changer le vecteur pour ne pas obtenir d'objets p>
Je crains que vous ayez un problème xy et de mélanger d'importants concepts de polymorphisme d'objet et de conception C ++ en général, mais voici une solution à ce que vous avez posé:
#include <vector>
#include <memory>
struct Human {
virtual ~Human() = default;
};
struct Parent;
struct Child: Human{
Child(std::string) {}
void addParent(std::weak_ptr<Parent> aParent) {
Parent = aParent;
}
private:
std::weak_ptr<Parent> Parent;
};
struct Parent: Human, std::enable_shared_from_this<Parent> {
Parent(std::string) {}
void addChild(Child aChild){
aChild.addParent(shared_from_this());
Children.push_back(aChild);
}
private:
std::vector<Child> Children;
};
int main() {
auto parent1 = std::make_shared<Parent>("Albert"); //create an object of class Parent parent1 with a name Albert.
Child child1("John");//create an object of a class Child child1 named John.
parent1->addChild(child1);
}
L'ajout faim_ptr code> / partagé_ptr code> au code de quelqu'un qui apprend est surchargé?
Oui, mais puisqu'il semble têtu de la conception de classe donnée, cela doit être fait. Sinon, vous obtiendrez des effets encore plus surprenants comme, de la tranchée et des problèmes de vie, c'est-à-dire des défauts SEG. De cette façon, j'ai déjà recommandé au PO de reconsidérer son design initial. Et apprendre davantage sur la durée de vie, les classes de stockage et le POO en général. Bien sûr, on pouvait simplement refuser de répondre aux questions de Newbie car ils sont faux, mais ceux-ci ne le font pas, au moins on devrait montrer de bonnes pratiques dans la mesure du possible. Et les pointeurs bruts sont dangereux et pas les meilleurs pratices.
S'il vous plaît jeter un oeil à mon commentaire, et mon implémentation . Il semble que vous ayez une idée fausse sur la façon dont std :: vecteur code> fonctionne.
Merci pour une explication détaillée. C'est très utile!
Vous avez principalement 2 numéros: p>
std :: vecteur code> stocker uniquement une partie humaine de parent code> / enfant code>. Li>.
ul> Vous avez rencontré un problème courant des programmeurs de Novice OOP: vous essayez de résoudre un problème relationnel en prolongeant des classes de l'OPO, au lieu de créer une classe relationnelle.
L'approche novice forte> p> Tout d'abord, continuons avec votre approche pour un peu ... bien sûr, chaque parent code> a un enfant code> et chaque enfant code> a un Parent code> et la manière naturelle semble stocker ces relations dans chaque classe. Ainsi: P> //Given, that we only have basic functionality, a struct is sufficient here...
struct ParentalRelation
{
Child child;
Parent parent;
};
Bonjour, merci beaucoup pour une explication aussi détaillée - très appréciée pour un débutant. Je pense que je rencontre toujours un problème de déclaration avancé - pouvez-vous aider? J'ai ajouté le code et les erreurs qu'il cède dans la modification de la question.
Votre code ne compilera ni ne fonctionnera, car un conteneur doit connaître la taille de ses éléments. (Dans ce cas std :: vecteur
@Kivis pas de problème! Désolé, c'est un peu délicat et j'ai laissé de côté quelques détails de la mise en œuvre pour rendre le code plus clair ... Ici, vous ne pouvez pas définir les fonctions membres à l'intérieur de la classe. Vous devez les déclarer et ensuite faire la définition à l'extérieur. Voici une implémentation de travail: goodbolt.org/z/hd4xhp
@Superlokkus Malgré votre prédiction, il compile et ça marche: D aussi loin que je le comprends (cela pourrait être faux), std :: vecteur parent code>.
Mon idée fausse est qu'ils ont changé l'exigence de type de T dans le vecteur
Mais merci de savoir que si vous ne m'avez pas dit, je n'aurais pas remarqué que le changement de C ++ 17.
@Superlokks Je suis désolé, mais je ne comprends pas ce que vous dites.
Votre code est toujours faux pour les C + 11 et 14 et ne garantit pas la compilation des bibliothèques standard pré-c ++ 17. C'est aussi la raison pour laquelle il n'a pas compilé sur le compilateur en ligne donné par l'OP.
@Superlokkus b b mais compile ... aa et travaille ... (voir goodbolt.org/z/hd4xhp < / a>) Il vous suffit d'obtenir l'ordre des déclarations et des définitions ....
@Superlokkus compare votre code avec le mien: vous définissez un parent célibataire pour l'enfant. Vous avez raison, cela ne fonctionne pas ... Cependant, ce n'est pas ce que je fais. J'ai un vecteur qui fonctionne juste bien.
@Superlokkus Je pense, je vous comprends du problème maintenant. Je l'ai posté comme une question séparée à: Stackoverflow.com/q/56975491/4759339
Tout fonctionne pour moi. Merci Jan! Et je suis content que cela a commencé une discussion :)
@ Jan.Sende Je me demandais, pourquoi ajoutez-vous également l'opérateur d'adresses et après les fonctions AddChild, AddParent et LinkchildToparent? J'essaie de comprendre cette adresse de mémoire et de l'entreprise des pointeurs en tout. Merci!
@Kivis Le & code> peut avoir plusieurs significations. À ce stade, il marque les paramètres comme un Référence . Ils se comportent un peu comme des pointeurs, mais ne sont pas exactement les mêmes. Vous en avez besoin parce que parent parent code> éditerait une copie de l'objet et laissez l'original derrière. Cependant, on pourrait écrire une version parent * parent code> à la place.
Y a-t-il un
humain code> qui n'est pas un enfant? Qu'est-ce que i> est i> (fonctionnalité) Aparent code> quelhumain code> (ouenfant code>) ne fait pas? En bref: votre conception n'est pas très utile.C'est un exemple de jouet pour illustrer ce que je veux la fonction addChild () à faire - je ne suis pas inquiet pour la conception à ce stade.
Moi-même est
ceci code> resp.* ceci code>Pourquoi ne pas simplement utiliser
ceci code>?Dans les membres non statiques de toute classe, le pointeur code> code> (fourni par le compilateur) identifie l'objet actuel. Au-delà de cela, les enfants et les parents ne sont pas des types distincts d'humains (assez de personnes sont simultanément). Je n'utiliserais donc pas
humain code> comme classe de base. Au lieu de cela, faites sansparent code> etenfant code> comme des classes distinctes. Puis chaquehumain code> peut avoir un ensemble d'enfants et un ensemble de parents, c'est-à-dire d'être un parent ou un enfant (ou avoir des parents et des enfants) est un attribut de chaquehumain code>, Pas la base de la définition de différents types dehumain code>.Voir ma réponse de réponse sur votre question ajoutée.