Wie von [namespace.udecl] / 18 angegeben:
[...] Eine using-Deklaration, die einen Konstruktor benennt, erzeugt kein Synonym; Stattdessen sind die zusätzlichen Konstruktoren zugänglich, wenn sie zugänglich wären, wenn sie zum Erstellen eines Objekts der entsprechenden Basisklasse verwendet werden, und die Verfügbarkeit der using-Deklaration wird ignoriert. [...]
Aus diesem Grund kompiliert der folgende Code nicht:
%Vor%Er gibt einen Fehler zurück, der bei allen großen Compilern mehr oder weniger der gleiche ist:
hier als geschützt erklärt
Auf der anderen Seite kompiliert der folgende Code:
%Vor%Sollte es nicht aus den gleichen Gründen, die zu einem Fehler im vorherigen Beispiel geführt haben, nicht kompiliert werden? Was erlaubt es zu kompilieren?
Im zweiten Fall wird erben des Konstruktors nicht wirksam. Nach den Regeln von gelöschten implizit deklarierten Standardkonstruktoren , das in der 2. Fallklasse D
verletzt nicht (es gibt ein wohlgeformtes B::B()
für D
); Der Compiler wird einen Standardkonstruktor als öffentliches Mitglied inline für D
deklarieren, wodurch D d{};
gut funktioniert.
...
T
hat eine direkte oder virtuelle Basis, die einen gelöschten Standardkonstruktor hat, oder sie ist mehrdeutig oder von diesem Konstruktor aus nicht zugänglich....
Im ersten Fall tritt Konstruktoren erben in Kraft:
(Betonung meiner)
Wenn die Überladungsauflösung einen geerbten Konstruktor auswählt, ist dies der Fall zugänglich, wenn es zugänglich wäre, wenn es zum Konstruieren eines Objekts verwendet wird der entsprechenden Basisklasse: die Erreichbarkeit der using-declaration, die es eingeführt hat, wird ignoriert .
Wenn die Überladungsauflösung einen der geerbten Konstruktoren auswählt, wenn Initialisieren eines Objekts einer solchen abgeleiteten Klasse, dann das Base-Subobjekt aus dem der Konstruktor geerbt wurde, wird mit geerbter Konstruktor und alle anderen Basen und Mitglieder von Derived sind wie vom Standardstandardkonstruktor (Standardmember) initialisiert Initialisierer werden verwendet, falls vorgesehen, andernfalls Standardinitialisierung findet statt).
Dann schlägt es wegen der Zugriffsisolierung fehl.
D
hat in diesem Fall keinen benutzerdefinierten Konstruktor, also generiert der Compiler einen (öffentlichen) für Sie, der B::B
aufruft (aber nicht wegen using
, das in diesem Fall keine Wirkung hat), Dieser compilergenerierte Konstruktor wird dann von main aufgerufen.
Obwohl D
hier keinen benutzerdefinierten Konstruktor hat, wird der vom Compiler generierte Konstruktor implizit gelöscht, weil B
nur einen Konstruktor hat, der ein int
akzeptiert. D
hat auch einen Konstruktor, der ein int
übernimmt ( using
hat das getan), aber dieser Konstruktor ist als protected
markiert und somit nicht von main
erreichbar.
Tags und Links c++ c++11 language-lawyer default-constructor inherited-constructors