32 votes

Opérateur de résolution de la portée

J'ai accidentellement trouvé ceci dans l'un des codes sources que je regardais. Donc, je donne un petit exemple similaire ici.

Dans le fichier test.h :

#include<iostream>

class test{
    int i;
public:
    test(){}
    //More functions here
};

Dans le fichier test.cpp :

#include "test.h"

int main()
{
    test test1;
    test::test test2;
    test::test::test test3;
    return 0;
}

Tout d'abord, y a-t-il une raison pour déclarer test2 de cette façon ? Deuxièmement, ce code se compile très bien avec la version 4.4.3 de g++ et les versions inférieures. Y a-t-il quelque chose dans la norme C++ qui dit que les opérateurs de résolution de portée sont ignorés quand il n'y a pas besoin de résoudre la portée ?

41voto

James McNellis Points 193607

Ce code n'est pas valide.

C'est un bug de g++ qui a accepté le code. Voir "g++ ne traite pas correctement le nom de la classe injectée". Le bogue a été résolu comme corrigé en 2009, il devrait donc être corrigé dans toute version récente de g++.

16voto

Jerry Coffin Points 237758

Pour clarifier la situation, comme précisé au §9/2 :

Un nom de classe est inséré dans l'étendue dans laquelle il est déclaré immédiatement après que le nom de classe est vu. Le nom de la classe est également inséré dans la portée de la classe elle-même ; c'est ce qu'on appelle le nom de la classe injectée. Pour des raisons de contrôle d'accès, le nom de classe injecté est traité comme s'il s'agissait d'un nom de membre public.

Cependant, comme spécifié dans le §3.4.3.1/1 :

Si le spécificateur de nom imbriqué d'un id qualifié désigne une classe, le nom spécifié après le spécificateur de nom imbriqué est recherché dans la portée de la classe (10.2), sauf dans les cas énumérés ci-dessous.

[ ... §3.4.3.1/2] :

Dans une recherche où le constructeur est un résultat acceptable de la recherche et où le spécificateur de nom imbriqué désigne une classe C :

- si le nom spécifié après le nested-name-specifier, lorsqu'il est recherché dans C, est le injected-class-name de C (Clause 9) [ ... ] le nom est considéré comme le nom du constructeur de la classe C.

[ ... exemple : ]

struct A { A(); };
[ ... ]
A::A a; // error, A::A is not a type name
struct A::A a2; // object of type A

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X