Remplacer champ de membre dans les classes dérivées
J'ai un extrait de code ci-dessous:
#include <iostream>
using namespace std;
class Base {
public:
Base() : b(0) {}
int get();
virtual void sayhello() { cout << "Hello from Base with b: " << b << endl; }
private:
int b;
};
int Base::get() {sayhello(); return b;}
class Derived : public Base {
public:
Derived(double b_):b(b_){}
void sayhello() { cout << "Hello from Derived with b: " << b << endl; }
private:
double b;
};
int main() {
Derived d(10.0);
Base b = d;
cout << "Derived b: " << d.get() << endl;
cout << "Base b: " << b.get() << endl;
}
Exécuter le fichier exécutable compilé et je trouve que le résultat est hors de mon attente sur mon llvm-g++ 4.2 de la machine. La sortie sur ma boîte est comme
Hello from Derived with b: 10
Derived b: 0
Hello from Base with b: 0
Base b: 0
Ce que je veux faire dans le code pour remplacer un membre de champ (b
) dans Derived
classe.
Car je pense que les deux Base
et Derived
besoin d'accéder à ce domaine, de définir une get
une fonction membre dans Base
, ainsi Derived
peut en hériter.
Puis-je essayer d'obtenir le champ de membre de différents objets.
Le résultat montre que je suis toujours d'origine b
dans Base
par d.get()
plutôt que dans Derived
, qui est ce que j'attendais le code pour le faire.
Rien de mal avec le code (ou ma compréhension)? Est-ce le comportement spécifié dans le cahier des charges? Quelle est la bonne façon de remplacer un membre du domaine et de définir correctement son getter et setter?
B::b
de D
sauf s'il est qualifié. Mais le caché, initialisé B::b membre de D
est copié comme il devrait être en place d'ici à la copie par défaut-ctor de B
, comme il se doit. Vos classes de base n'est pas juste de commencer à l'aide de leur non-cachés de la classe dérivée des variables membres par une sorte d'osmose. Ils ne sont même pas conscients qu'ils sont là.OriginalL'auteur Summer_More_More_Tea | 2013-10-10
Vous devez vous connecter pour publier un commentaire.
La nouvelle
b
ajouté dans la classe dérivée ne modifie pas la base de lab
. Il vient de cache.Donc, dans la classe dérivée, vous avez deux
b
et la méthode virtuelle tirages correspondantb
.0
, c'est à direb
valeur deBase
, lorsque j'utilised.get()
.Parce que
get()
n'est pas virtuel et il retourneb
défini dansBase
classe. Il ne sait rien à propos deDerived
classe, de sorte qu'il ne peut évidemment pas se renvoyer la valeur deDerived::b
membre. Seulementsayhello()
est virtuel, donc c'est la seule méthode qui peut revenirb
deDerived
.d'abord, vous ne devriez pas cacher les variables de cette façon.
Donc la bonne façon? Pourriez-vous nous en former une idée de réponse? Merci à vous :).
Vous annuler uniquement les fonctions, et non pas des données membres.
OriginalL'auteur deepmax
Vous ne pouvez pas tout simplement remplacer un membre de domaine, et que
Base::get
est compilé, leb
variable est résolu àBase::b
si cette méthode utilise toujours cette valeur et non pas une valeur d'un autre champ avec le même nom dans une classe dérivée.La manière habituelle pour remplacer un attribut est de remplacer le chemin d'accès, c'est à dire remplacer les accesseurs (getter et setter).
Vous pouvez obtenir quelque chose comme ça par la décoration de la lecture, mais de la lecture de type de retour est toujours le même:
Base
?que voulez-vous dire? Vous ne voulez pas remplacer la lecture? Ensuite, il ne sera pas possible directement. Si vous voulez des quelques supplémentaires comportement à toujours faire de la lecture, l'utilisation d'un sous-jacent (protégé?) virtuel de lecture que vous appelez dans votre décoré de lecture. J'ai éditer mon post avec un exemple
OriginalL'auteur Geoffroy
Je ne suis pas sûr que je vous comprends bien, mais par "remplacer" tu veux dire "remplacer", vous pouvez utiliser un modèle:
Vous code dans
main
était aussi tenterBase b = d;
qui conduirait à découpage, les correctifs et fait en sorte que vous n'avez pas accidentellement l'utilisationBase<int>
au lieu deBase<double>
.Live
b
deBase
avecd.get()
.Dans votre code
d.get()
appelle la non-virtuelint Base::get()
qui, évidemment, accède àBase::b
qui est unint
qui a été initialisé avec0
.Même
get
commevirtual
ne pouvez pas résoudre le problème. Vous devez remplacerget
dans la classe dérivée.Dans la Fpo code le type de retour de
get()
serait différent, de sorte que vous ne pouvez pas simplement le remplacer. Ou vous auriez à accepter que les dérivésdouble
est converti àint
.OriginalL'auteur Daniel Frey
vous devez réécrire votre Dérivés::ctor comme suit:
Et supprimer déposé
b
dans la classe Dérivée. Au lieu de cela marqueb
dans leBase
classe protégée.MODIFIER
Ignorer tout cela
J'ai trouvé un problème dans votre code:
Vous êtes copie objet dérivé à la base. Il copie seulement de la base de champs. Si vous voulez polymorphisme essayer la prochaine:
b
dansDerived
avec un autre type, c'est à dire changer la mise en œuvre de la structure de données sous-jacente. Je comprends votre réponse, cependant,b
ici est toujours de typeint
.OriginalL'auteur zabulus