Pourquoi est purement virtuel/classe abstraite, le constructeur, en particulier pour une protection de l'const variables de membre?
J'ai purement virtuel de la classe définies en tant que telles:
class BaseClass {
protected:
const int var;
public:
void somefun() = 0; //what I mean by a purely virtual class
//stuff...
};
Si je n'ai pas d'ajouter un constructeur défini comme tel:
BaseClass(const int & VAR) : var(VAR) {};
que j'aurais par la suite à jamais dérivée de la classe, ma classe dérivée ne peut pas initialiser la variable const var selon la valeur qu'il veut. Maintenant, j'ai vraiment comprendre ce qui se passe ici. Avant de construire une classe dérivée, un constructeur de la classe de base est appelé, à quel point const variables de membre doit être initialisé. Ma question n'est pas "comment faire pour que mon code de travail" genre de question, qui a déjà été fait. Ma question est de savoir pourquoi le compilateur pense que c'est nécessaire. Pour une purement virtuel de la classe, je ne devrais pas avoir le droit d'écrire quelque chose comme:
class DerivedClass : BaseClass {
public:
DerivedClass() : var(SOME_VALUE) {};
}
Si le compilateur sait qu'un appel à une BaseClass constructeur sera nécessairement suivie par un appel à une classe dérivée de constructror (depuis un objet de type abstrait ne peut jamais être instancié) ne devrait-il pas nous donner un peu plus de marge de manœuvre?
Est-ce une conséquence de la manière dont C++ choisit de contourner le Diamant problème? Même si c'était le cas, n'est pas le compilateur au moins en quelque sorte accepter la possibilité que const variable de membre de purement virtuel fonctions seront définies dans les classes dérivées? Est-ce trop compliqué ou qui ne plaisante pas avec le C++ solution pour le Diamant problème?
Merci pour l'aide tout le monde.
Je pense que c'est vrai qu'il le fait. Mais est-ce vraiment nécessaire dans cette situation?
OriginalL'auteur ticster | 2012-02-22
Vous devez vous connecter pour publier un commentaire.
Ce n'est pas "purement virtuel" (ce que vous entendez par là) - il contient un membre de données.
Les membres de la classe ne peuvent être consultés par l'initialiser la liste d'un constructeur de cette classe, et non pas d'une classe dérivée. C'est comment l'initialisation des objets est spécifié: tous les membres qui sont initialisées, sont initialisées avant le corps du constructeur commence.
Constante des objets doit être initialisé, puisqu'ils ne peuvent pas être affectés à une valeur plus tard.
Par conséquent, une classe avec une constante membre de données doit l'initialiser à chaque constructeur.
OK, qui est connu comme "abstrait". Cela signifie que la classe ne peut pas être instanciée à l'exception de la classe de base, mais n'a rien à faire avec tous les membres de données qu'il pourrait avoir. Ils se comportent exactement de la même manière comme ils le feraient dans un non-classe abstraite.
Mais mon point est, ont-ils? Sachant qu'un objet de ce type ne sera jamais instanciée, ne pas le compilateur nous donner un peu plus grande marge de manœuvre?
Qui permettrait d'ajouter un certain nombre de complications (diagnostic de l'échec de l'initialisation, la préservation de l'initialisation de l'ordre, et probablement d'autres que je ne peux pas pense tout de suite) pour aucun avantage autre que vous permettant d'omettre un petit fragment de code. Je suppose que c'est pourquoi il n'est pas permis (en supposant que toute personne, même considéré comme le permettant), mais si vous voulez vraiment connaître les raisons pour lesquelles vous pourriez avoir à demander au comité des langues.
Merci pour la réponse. J'ai pensé qu'il était juste plus de complications que cela méritait, mais j'ai quand même demandé si il ne pourrait pas être plus large avantage de permettre un traitement spécial des classes abstraites qui prend en compte le fait que le constructeur de base seul ne sera jamais appelé. Je suppose que non, et les complications que vous avez donné doivent l'emporter sur eux.
OriginalL'auteur Mike Seymour
La construction d'un objet se produit dans un ordre spécifique. La classe de base doit être entièrement construit avant le constructeur d'une classe dérivée est exécuté, ainsi que les dérivés constructeur travaille avec un entièrement formé et valide de l'objet de base. Si l'initialisation de la base de variables membres ont été mis hors tension jusqu'à ce que la construction de la classe dérivée, cet invariant serait rompu.
OriginalL'auteur Mark Ransom
Non, mais vous pouvez(et dans ce cas devrait) écrire quelque chose comme ceci:
Dans l'exemple que vous nous avez donné, vous avez essayé d'initialiser BaseClass::var de DerivedClass::DerivedClass directement, sans utiliser de BaseClass constructeur. En appelant le constructeur parent, vous pouvez initialiser réellement le var variable d'instance. Cela répond au "comment faire pour que mon code fonctionne" question.
Comme je l'ai dit, j'ai déjà compris et fait. J'essaie juste de comprendre pourquoi il est nécessaire dans ce cas, en particulier parce que BaseClass ne peut jamais être initialisé.
OriginalL'auteur mfontanini