J'ai deux classes de base avec des clauses using
class MultiCmdQueueCallback {
using NetworkPacket = Networking::NetworkPacket;
....
}
class PlcMsgFactoryImplCallback {
using NetworkPacket = Networking::NetworkPacket;
....
}
Je déclare ensuite une classe
class PlcNetwork :
public RouterCallback,
public PlcMsgFactoryImplCallback,
public MultiCmdQueueCallback {
private:
void sendNetworkPacket(const NetworkPacket &pdu);
}
le compilateur signale ensuite une référence d'erreur à 'NetworkPacket' est ambigu 'sendNetworkPacket (NetworkPacket & ...'
Désormais, les deux «clauses d'utilisation» se résolvent dans la même classe sous-jacente. Networking: NetworkPacket
et en fait si je remplace la déclaration de méthode par:
void sendNetworkPacket(const Networking::NetworkPacket &pdu);
il compile très bien.
Pourquoi le compilateur traite-t-il chaque clause using comme un type distinct, même si elles pointent toutes les deux vers le même type sous-jacent? Est-ce obligatoire par la norme ou avons-nous un bug de compilation?
c++
using-declaration
Andrew Goedhart
la source
la source
NetworkPacket
- dans MultiCmdQueueCallback, dans PlcMsgFactoryImplCallback, dans la mise en réseau. Lequel utiliser doit être spécifié. Et je ne pense pas que la misevirtual
en place sera d'une quelconque utilité ici.Réponses:
Avant d'examiner le type résultant d'alias (et l'accessibilité)
on regarde les noms
et en effet,
NetworkPacket
pourrait êtreMultiCmdQueueCallback::NetworkPacket
PlcMsgFactoryImplCallback::NetworkPacket
Le fait qu'ils indiquent tous les deux
Networking::NetworkPacket
est sans importance.Nous effectuons la résolution des prénoms, ce qui entraîne une ambiguïté.
la source
error: [...] is private within this context
.class A { public: void f(char, int) { } private: void f(int, char) { } }; void demo() { A a; a.f('a', 'd'); }
- pas la même chose, mais la résolution de surcharge fonctionne de la même manière: tenez compte de toutes les fonctions disponibles, uniquement après avoir sélectionné celle appropriée, tenez compte de l'accessibilité ... Dans un cas donné, vous obtenez également une ambiguïté; si vous modifiez la fonction privat pour accepter deux caractères, elle sera sélectionnée bien que privée - et vous rencontrez l'erreur de compilation suivante.Vous pouvez simplement résoudre l'ambiguïté en sélectionnant manuellement celle que vous souhaitez utiliser.
Le compilateur recherche uniquement les définitions dans les classes de base. Si le même type et / ou alias est présent dans les deux classes de base, il se plaint simplement de ne pas savoir lequel utiliser. Peu importe que le type résultant soit le même ou non.
Le compilateur recherche uniquement les noms à la première étape, totalement indépendant si ce nom est une fonction, un type, un alias, une méthode ou autre. Si les noms sont ambigus, aucune autre action n'est effectuée à partir du compilateur! Il se plaint simplement du message d'erreur et s'arrête. Il suffit donc de résoudre l'ambiguïté avec l'instruction using donnée.
la source
De la documentation :
Bien que ces deux
using
clauses représentent le même type, le compilateur a deux choix dans la situation suivante:Il peut choisir entre:
MultiCmdQueueCallback::NetworkPacket
etPlcMsgFactoryImplCallback::NetworkPacket
car il hérite des deux classes
MultiCmdQueueCallback
et desPlcMsgFactoryImplCallback
classes de base. Un résultat de la résolution du nom du compilateur est une erreur d'ambiguïté que vous avez. Pour résoudre ce problème, vous devez explicitement demander au compilateur d'utiliser l'un ou l'autre comme ceci:ou
la source
class C { void f(uint32_t); }; void C::f(unsigned int) { }
(à condition que l'alias corresponde). Alors pourquoi une différence ici? Ils sont toujours du même type, confirmé par votre citation (que je ne considère pas suffisant pour expliquer) ...class C : public A, public B { void f(A::D); }; void C::f(B::D) { }
- au moins GCC accepte.Il y a deux erreurs:
privé-privé
Je ne vois pas de problème que le compilateur se plaint d'abord du deuxième problème parce que l'ordre n'a pas vraiment d'importance - vous devez résoudre les deux problèmes pour continuer.
public-public
Si vous modifiez la visibilité des deux
MultiCmdQueueCallback::NetworkPacket
etPlcMsgFactoryImplCallback::NetworkPacket
en public ou protégé, le deuxième problème (ambiguïté) est évident - ce sont deux alias de type différents bien qu'ils aient le même type de données sous-jacent. Certains peuvent penser qu'un compilateur "intelligent" peut résoudre cela (un cas spécifique) pour vous, mais gardez à l'esprit que le compilateur doit "penser en général" et prendre des décisions basées sur des règles globales au lieu de faire des exceptions spécifiques à la casse. Imaginez le cas suivant:Le compilateur doit-il traiter les deux de
NetworkPacketID
la même façon? Bien sûr que non. Parce que sur un système 32 bits,size_t
est 32 bits de long toutuint64_t
est toujours de 64 bits. Mais si nous voulons que le compilateur vérifie les types de données sous-jacents, il ne peut pas distinguer ceux sur un système 64 bits.public-privé
Je crois que cet exemple n'a aucun sens dans le cas d'utilisation d'OP, mais puisque nous résolvons ici des problèmes en général, considérons que:
Je pense que dans ce cas, le compilateur doit traiter
PlcNetwork::NetworkPacket
commePlcMsgFactoryImplCallback::NetworkPacket
parce qu'il n'a pas d'autre choix. Pourquoi il refuse toujours de le faire et blâme l'ambiguïté est un mystère pour moi.la source