2009-10-17 7 views
1

Est-ce que quelque chose de similaire est possible? De cette façon, il produit une erreur.Membres virtuels sans méthode

class A { 
    public: 
    virtual std::string key; 
}; 

class B : public A { 
    public: 
    std::string key; 
}; 

int main() 
{ 
    A a; 
    a.key = "Foo"; 
    return 1; 
} 
+0

Le comportement que vous recherchez n'est pas clair. Il serait utile si vous ajoutez plus de code dans la fonction main() expliquant le comportement que vous recherchez. Non, cela n'a pas de sens de rendre un membre de données virtuel. – zumalifeguard

Répondre

8

Non, car cela n'a pas vraiment de sens. Rappelez-vous qu'une sous-classe contient tous les membres de sa classe parente; par conséquent, B a toujours std::string key. En outre, depuis Bstd::string key est le même type, c'est absolument identique à A - alors quel était le point de l'annuler?

Notez également que lors de la construction, lorsque nous exécutons le constructeur A, les méthodes virtuelles B ne seront pas appelées. Cela signifie que si nous accédons à key pendant la construction de A, nous obtiendrons la clé de A - mais lorsque B sera construit, cela signifiera que key sera ombrée, ses données étant totalement inaccessibles.

Cela dit, si vous voulez vraiment faire quelque chose comme ça, pour une raison quelconque, vous aurez besoin d'utiliser une fonction accesseur virtuelle:

class A { 
    private: 
    std::string m_key; 
    public: 
    virtual std::string &key() { return m_key; } 
    virtual const std::string &key() const { return m_key; } 
}; 

class B : public A { 
    private: 
    std::string m_key; 
    public: 
    virtual std::string &key() { return m_key; } 
    virtual const std::string &key() const { return m_key; } 
}; 

int main() 
{ 
    B b; 
    b.key() = "Foo"; 
    return 0; 
} 
0

Les méthodes de classe sont le code. Le code est constant. Chaque méthode de classe particulière a un comportement fixe prédéfini défini lors de la compilation qui ne peut pas être modifié au moment de l'exécution. Pour cette raison, afin d'avoir des classes polymorphes, nous devons écrire plusieurs versions différentes des différentes méthodes à l'avance (ie à la compilation), puis "attacher" un ensemble spécifique de ces versions aux instances de la classe au moment de l'exécution. le comportement d'exécution spécifique de chaque instance.

Avec les membres de données, la situation est complètement différente. Les membres de données ne sont pas corrigés. Ils sont changeants. Ils contiennent des valeurs et ces valeurs peuvent être modifiées librement au moment de l'exécution. Cela seul rend les membres de données intrinsèquement «virtuels» par eux-mêmes. Vous n'avez pas besoin d'introduire une "version" différente du membre de données dans la classe dérivée. Au lieu de cela, vous devez simplement mettre une valeur différente dans un membre de données déjà existant. Cela seul est déjà analogue à la «virtualité» des méthodes de classe. De plus, cette "virtualité des données" est encore plus flexible que la "virtualité" des méthodes, car avec les membres de données, vous n'êtes pas limité à un ensemble prédéterminé de valeurs. Ce que vous proposez ressemble cependant à un degré plus élevé de «virtualité»: non seulement la valeur de membre de données est modifiable, mais le membre de données lui-même est redéfinissable. (Appelez cela méta-virtualité, ou super-virtualité ou double-virtualité.) Mais quel serait le point, le bénéfice, le cas d'utilisation de cette fonctionnalité? Personnellement, je ne le vois pas tout de suite et votre échantillon de code ne dit pas exactement.

Questions connexes