C++ de la Création de la Classe Enfant d'une Classe Parent qui a déjà été initialisé
J'ai une classe "Joueur". Ses membres sont de simples chaînes et ints et j'ai Getters et Setters pour chacun de ces...trucs de base: (il y a une charge de membres donc j'ai juste donné 3 pour réduire le code):
JOUEUR.H
class Player
{
private:
string Name;
string Role;
int FFDefence;
......etc
public:
//constructor function
Player(
string Name = "Not Stated",
string vRole = "Not Stated",
int vFFDefence = 0,
......etc
)
//Getter Functions
string GetName() const;
string GetRole() const;
int GetFFDefence() const;
.....etc
//Setter Functions
void SetName (string x);
void SetRole(string x);
void SetFFDefence(int x);
......etc
};
PLAYER.CPP
Player::Player( string vName,
string vRole,
int vFFDefence,
......etc
{
Name = vName;
Role = vRole;
FFDefence = vFFDefence,
......etc
}
//getter functions
string Player::GetName() const {return Name; };
string Player::GetRole() const {return Role; };
int Player::GetFFDefence() const {return FFDefence; };
.....etc
//Setter Functions
void Player::SetName(string x) { Name = x ; };
void Player::SetRole(string x) { Role = x ; };
void Player::SetFFDefence(int x) { FFDefence = x ; };
......etc
Donc oui - jolie la tourbière de la norme......maintenant, j'ai une deuxième classe où l'une des fonctions de membre est un Joueur de Classe elle-même.
De la PÂTE.H
class Batter
{
private:
Player ID;
int Touch;
....etc
public:
Batter(Player vID, int vTouch = 0....etc);
//Getter Functions
string GetRole() const;
int GetFFDefence() const;
int GetBFDefence() const;....and so on.
OK - c'est le code de la route!!!!
Donc, je l'ai fais tout ce que je veux, en termes de passage de variables dans et à l'extérieur....donc je peux créer
Player Dave ("Dave", "Opener", 98, ....etc)
puis plus tard (quand j'en ai besoin) créer
Batter OnStrike (Dave, 10, .....etc)
Toutes les sauces....OK, donc j'ai commencé à chercher dans l'héritage et réalisé que ce est ce que je devrais faire....de retour de la conversion n'est pas un problème (fait avec des matrices et des vecteurs de l'autre jour)...
Voici mon problème:
Avec ce que j'ai maintenant, je peux créer "le Joueur Dave" et ensuite le passer dans la sous-classe de la Pâte à chaque fois que j'en ai besoin. Comment puis-je faire de même avec l'héritage traditionnel? Comment dois-je prendre une instance spécifique (déjà créé) du Joueur et de l'utiliser en tant que parent pour une instance particulière de la classe enfant de la Pâte? Aussi loin que je peux en déduire pour le moment, vous devez créer deux en même temps.
Vous devez vous connecter pour publier un commentaire.
Initialiser votre objet de base avec l'objet condition:
D'autre part, il y a la question de savoir si l'héritage de
Batter
dePlayer
est l'outil approprié dans votre cas. Le fait que vous passez unPlayer
opposer à la construction d'indices sur le fait qu'un Joueur peut devenir un batteur, et plus tard peut-être aussi arrêter d'être une pâte. C'est,Batter
est en fait un rôle lequel le joueur peut temporairement. Par conséquent, il peut être une meilleure idée de séparer lesPlayer
objet de la rôle, en ayant unRole
hiérarchie oùBatter
etPitcher
dériver deRole
, etPlayer
a une méthode qui retourne le rôle actuel, et un autre qui peut attribuer un autre rôle pour le joueur.L'idée avec le polymorphisme, c'est que si vous avez un peu de classe:
Puis tous pâte est aussi un joueur. Ainsi, par exemple, si vous avez eu une pâte appelée
dave
, vous seriez en mesure d'utiliserdave
où un Joueur a été prévu. Vous pourriez par exemple:Être prudent pour éviter de découpage, qui est accidentellement lorsque vous faites une classe de base copie d'une sous-classe (ce qui ne permet pas de conserver la sous-classe spécifique de l'état. Si vous avez besoin de passer
dave
autour, assurez-vous de ne reportez-vous àdave
, de ne pas copierdave
.dave
n'aime pas être copié.)Exactement comment vous construisez vos joueurs et de pâtes est à vous. Par exemple, il peut être de constructeurs avec ces signatures:
Dans certaines circonstances, cela peut être pratique, mais elle n'est pas particulièrement efficace, parce que vous devez créer et de copie de la classe de base (pas que l'efficience est une grosse affaire pour les petites classes comme ça, mais il n'y a aucun point dans essayer faire les choses de la muette chemin). Vous serait mieux de faire un constructeur qui prend tout ce dont il a besoin, et utilise des sous-objet d'initialisation:
Mais votre mise en œuvre est finalement à vous.
Vous faites l'agrégation ici, pas d'héritage. Une Pâte a un joueur. Héritage serait un batteur est un joueur.
Votre conception est bonne, vous ne voulez pas faire de l'héritage de cette.
Alors que c'est bien de dire un Batteur est toujours un Joueur à partir d'un point de vue conceptuel, dans ce cas, lorsque vous êtes face à un Frappeur, beaucoup de ce joueur décrit est hors de propos et dans ses relations avec eux en tant que joueur, ils peuvent ne pas être au bâton.
Le Baseball est un peu étranger à moi, mais si vous êtes allé vers le bas de l'héritage de la route, vous auriez descendants de joueur pour chaque rôle dans l'équipe et dans un désordre quand votre lanceur est sorti de chauve-souris.
Une illustration classique de l'héritage de la route.
Est
Où avez-vous mis chauve-souris et l'Autruche?
Vous êtes de gauche avec le fait de dire une chauve-souris est un oiseau, d'inventer une nouvelle classe FlyingRodent, ou de Rongeurs ayant deux parents...
Tous ce qui va conduire à une confusion bug fest.
Afficher tous des inconscients atteint pour l'héritage marteau avec une extrême méfiance.
Ça dépend vraiment de la façon dont vous voulez vraiment votre code de le prendre en compte.
Une donnée
Player
jamais devenir autre chose qu'unBatter
? Si on le peut, alors il est probablement préférable d'utiliser l'agrégation (de manière similaire à la façon dont vous le faites aujourd'hui).Si vous êtes l'agrégation, alors peut-être utiliser une autre classe afin de conserver les données. Vous pourriez avoir un PlayerInfo classe ou structure et d'agrégats:
Si vous voulez réellement l'héritage, puis d'autres réponses ici vous dire ce que vous devez faire - construire une instance de
Batter
et de passer sur les arguments du constructeur à un constructeur de la classe, vous en dérivent (par exempleBatter
) pour l'initialiser.Réfléchissez bien à ce que vous essayez d'exprimer dans votre code.
La raison pour laquelle vous voulez avoir
Batter
dérivé dePlayer
est si vous avez besoin de fonctions virtuelles dansPlayer
qui sont mis en œuvre dansBatter
et faire quelque chose de différent, selon qu'il est ou non unPlayer
ou unBatter
.En aparté, de son mieux pour garder les classes de base abstraites, si possible, de sorte
Player
ne serait jamais instanciée directement et aurait toujours besoin d'être dérivée. Je vous recommande la lecture de Scott Meyers Plus Effective C++ " pour comprendre pourquoi il en est. Il y a une section consacrée à cela. En fait, certains des points les plus fins de l'héritage et OO le design en général sont très bien expliqué.Ce que vous voulez vraiment est quelque chose de légèrement différent selon l'endroit où vous prévoyez que votre modèle de changement, et en outre où avez-vous besoin d'avoir le comportement dynamique possible grâce à l'utilisation de fonctions virtuelles?
Vous pourriez avoir un
Player
classe qui a tous de votre joueur des détails spécifiques. Alors vous pourriez avoir unPlayerBehaviour
classe qui implémente ce que le joueur n':Donc, héritant
Batter
dePlayer
modèles de la situation comme unBatter
est-unPlayer
.Avoir un
Behaviour
modèles de la situation comme unPlayer
a-unBehaviour
comme unBatter
.Arrêtez d'utiliser le "parent" et "enfant" de la terminologie, de penser à "la base" des classes et des "dérivés" des classes ... c'est ce que tout le monde les appelle. "Parent" et "enfant" peut être utilisé dans de trop nombreux autres moyens (par exemple, un objet qui possède un autre), il est donc confusion terminologique si vous parlez d'une relation d'héritage.
La classe dérivée contient l'intégralité d'une instance du type de base à l'intérieur de lui-même. Lorsque le dérivé constructeur commence l'exécution de la première chose qu'il fait est de construire l'ensemble de ses bases, ce qui n'est en les appelant par leurs constructeurs. Si la classe dérivée peut contrôler la façon dont la base est construite en lui passant les bons arguments:
Cela crée à la fois la
Base
etDerived
objets en même temps (l'un dans l'autre) ce qui est probablement ce que vous voulez.Si vous ne disposez déjà d'une
Base
objet et que vous souhaitez la base de l'objet dérivé être le même que l'autre, alors vous pouvez passer un objet à copier:Que ce n'est pas l'existant
Base
objet,b
, à l'intérieur de laDerived
un, au lieu de cela, il fait l'objet de base d'une copie de l'objetb
, par l'appel de laBase
constructeur de copie, donc il y a maintenant deuxBase
objets, l'originalb
et celui à l'intérieur ded
. Ce qui est plus proche de votre code d'origine, où laBatter
contient unPlayer
membre, mais maintenant c'est une classe de base n'est pas membre.Si vous ne voulez pas utiliser l'héritage, la première forme est probablement plus approprié, lorsque vous passez arguments à la classe dérivée et il utilise ces arguments pour créer la base.
Base(name)
etBase(b)
constructeur invocations, jusqu'à ce que ces constructeurs exécuter la base n'existe pas, donc il n'y a rien à "remplacer". Le nom de base est de ne jamais "non déclaré". Avant de la classe de base est construit son nom n'existe même pas, et dans le constructeur, il se construit avec l'argumentnm
, par l'expressionname(nm)
, donc après qu'il est "Dérivée Dave" ou "Barry de Base"