Ich habe zwei Basisklassen mit using-Klauseln
class MultiCmdQueueCallback {
using NetworkPacket = Networking::NetworkPacket;
....
}
class PlcMsgFactoryImplCallback {
using NetworkPacket = Networking::NetworkPacket;
....
}
Ich erkläre dann eine Klasse
class PlcNetwork :
public RouterCallback,
public PlcMsgFactoryImplCallback,
public MultiCmdQueueCallback {
private:
void sendNetworkPacket(const NetworkPacket &pdu);
}
Der Compiler kennzeichnet dann einen Fehlerverweis auf 'NetworkPacket', der nicht eindeutig ist. 'sendNetworkPacket (NetworkPacket & ...'
Jetzt werden beide 'using-Klauseln' in dieselbe zugrunde liegende Klasse Networking: NetworkPacket aufgelöst
und in der Tat, wenn ich die Methodendeklaration durch Folgendes ersetze:
void sendNetworkPacket(const Networking::NetworkPacket &pdu);
es kompiliert gut.
Warum behandelt der Compiler jede using-Klausel als einen eigenen Typ, obwohl beide auf denselben zugrunde liegenden Typ verweisen? Ist dies vom Standard vorgeschrieben oder haben wir einen Compiler-Fehler?
c++
using-declaration
Andrew Goedhart
quelle
quelle
NetworkPacket
- in MultiCmdQueueCallback, in PlcMsgFactoryImplCallback, in Networking. Welches verwendet werden soll, sollte angegeben werden. Und ich denke nicht, dass Puttenvirtual
hier hilfreich sein wird.Antworten:
Bevor Sie sich den resultierenden Alias-Typ (und die Barrierefreiheit) ansehen
Wir schauen uns Namen an
und in der Tat,
NetworkPacket
könnte seinMultiCmdQueueCallback::NetworkPacket
PlcMsgFactoryImplCallback::NetworkPacket
Die Tatsache, auf die beide hinweisen,
Networking::NetworkPacket
ist irrelevant.Wir führen die Auflösung von Vornamen durch, was zu Mehrdeutigkeiten führt.
quelle
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'); }
- Nicht dasselbe, aber die Überlastungsauflösung funktioniert gleich: Berücksichtigen Sie alle verfügbaren Funktionen, nur nachdem Sie die entsprechende ausgewählt haben, berücksichtigen Sie die Zugänglichkeit ... In einem bestimmten Fall erhalten Sie auch Mehrdeutigkeiten. Wenn Sie die private Funktion so ändern, dass zwei Zeichen akzeptiert werden, wird sie ausgewählt, obwohl sie privat ist - und Sie stoßen auf den nächsten Kompilierungsfehler.Sie können die Mehrdeutigkeit einfach beheben, indem Sie manuell auswählen, welche Sie verwenden möchten.
Der Compiler sucht nur nach den Definitionen in den Basisklassen. Wenn in beiden Basisklassen der gleiche Typ und / oder Alias vorhanden ist, wird lediglich beanstandet, dass nicht bekannt ist, welcher Typ verwendet werden soll. Es spielt keine Rolle, ob der resultierende Typ der gleiche ist oder nicht.
Der Compiler sucht nur im ersten Schritt nach Namen, völlig unabhängig, ob dieser Name eine Funktion, ein Typ, ein Alias, eine Methode oder was auch immer ist. Wenn die Namen nicht eindeutig sind, wird vom Compiler keine weitere Aktion ausgeführt! Es beschwert sich einfach mit der Fehlermeldung und stoppt. Lösen Sie also einfach die Mehrdeutigkeit mit der angegebenen using-Anweisung.
quelle
Aus den Dokumenten :
Obwohl diese beiden
using
Klauseln denselben Typ darstellen, hat der Compiler in der folgenden Situation zwei Möglichkeiten:Es kann wählen zwischen:
MultiCmdQueueCallback::NetworkPacket
undPlcMsgFactoryImplCallback::NetworkPacket
weil es von beiden
MultiCmdQueueCallback
undPlcMsgFactoryImplCallback
Basisklassen erbt . Ein Ergebnis der Namensauflösung des Compilers ist ein Mehrdeutigkeitsfehler, den Sie haben. Um dies zu beheben, müssen Sie den Compiler explizit anweisen, das eine oder andere wie folgt zu verwenden:oder
quelle
class C { void f(uint32_t); }; void C::f(unsigned int) { }
(vorausgesetzt, der Alias stimmt überein). Warum also ein Unterschied hier? Sie sind immer noch vom gleichen Typ, bestätigt durch Ihr Zitat (das ich nicht für ausreichend halte, um es zu erklären) ...class C : public A, public B { void f(A::D); }; void C::f(B::D) { }
- Zumindest akzeptiert GCC.Es gibt zwei Fehler:
privat-privat
Ich sehe kein Problem, dass sich der Compiler zuerst über das zweite Problem beschwert, da die Reihenfolge nicht wirklich wichtig ist - Sie müssen beide Probleme beheben, um fortzufahren.
öffentlich-öffentlich
Wenn Sie die Sichtbarkeit von beiden ändern
MultiCmdQueueCallback::NetworkPacket
undPlcMsgFactoryImplCallback::NetworkPacket
entweder öffentlich oder geschützt, ist das zweite Problem (Mehrdeutigkeit) offensichtlich - dies sind zwei verschiedene Typ-Aliase, obwohl sie denselben zugrunde liegenden Datentyp haben. Einige mögen denken, dass ein "kluger" Compiler dies (einen bestimmten Fall) für Sie lösen kann, aber denken Sie daran, dass der Compiler "allgemein denken" und Entscheidungen auf der Grundlage globaler Regeln treffen muss, anstatt fallspezifische Ausnahmen zu treffen. Stellen Sie sich folgenden Fall vor:Sollte der Compiler beide
NetworkPacketID
gleich behandeln? Sicher nicht. Denn auf einem 32-Bit-Systemsize_t
ist es 32-Bit lang, währenduint64_t
es immer 64-Bit ist. Wenn der Compiler jedoch nach zugrunde liegenden Datentypen suchen soll, kann er diese auf einem 64-Bit-System nicht unterscheiden.öffentlich-privat
Ich glaube, dieses Beispiel macht im Anwendungsfall von OP keinen Sinn, aber da wir hier allgemein Probleme lösen, betrachten wir Folgendes:
Ich denke in diesem Fall sollte der Compiler so behandeln,
PlcNetwork::NetworkPacket
als hättePlcMsgFactoryImplCallback::NetworkPacket
er keine anderen Möglichkeiten. Warum es sich immer noch weigert und die Mehrdeutigkeit beschuldigt, ist mir ein Rätsel.quelle