Vererbte Konstruktoren, Standardkonstruktor und Sichtbarkeit

8

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?

    
skypjack 17.10.2016, 08:42
quelle

2 Antworten

3

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.

    
songyuanyao 17.10.2016, 09:02
quelle
5
%Vor%

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.

%Vor%

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.

    
Sombrero Chicken 17.10.2016 08:57
quelle