Ce qui suit permet d'appeler les attributs/fonctions cachés du fait d'un héritage ou faire appel à la fonction virtuelle d'un parent même si celle-ci est redéfinie dans un fil.
Ce principe est plus connu à l'intérieur d'une classe est utilisé avec l’héritage:
struct A
{
virtual int f() { return 3; }
virtual ~A(){}
};
struct B : A
{
virtual int f()
{ return A::f() + 3; } // Utilise la fonction f() du parent
};
Mais il peut aussi s'utiliser à l'extérieur d'une classe. Le A::f()
fait référence à une fonction de l'objet lié au pointeur this. Donc this->A::f()
est syntaxiquement valide. Ce qui veut dire qu'on peut faire référence à n'importe quel membre contenu dans l'objet.
struct A { int n = 2; };
struct B : A { int n = 3; };
B b;
b.n == 3
b.A::n == 2
struct C { virtual int f(){ return 2; } };
struct D : C { int f(){ return 3; } };
D d;
b.f() == 3
b.C::f() == 2
Cette technique est utilisé pour par exemple changer le buffer d'un fstream. La méthode std::ios::rdbuf(std::streambuf*)
étant cacher par std::ofstream::rdbuf()
c'est un moyen plus simple que le cast en une référence sur std::ios.
std::ofstream os("...");
//...
static_cast<std::ios&>(os).rdbuf(buf);
//ou
os.std::ios::rdbuf(buf);
1 commentaire:
Bonjour,
Pour aller plus loin, de manière général qualifier un nom (ie le faire précéder de ::) à tendance à désactiver plusieurs mécanismes :
- Dans ton article le polymorphisme
- La decay conversion, ca explique qu'on peut faire foo pour passer une fonction à une autre mais qu'on doit faire &A::foo si la fonction est membre.
- Le lookup
Et probablement d'autre cas. La conclusion étant donc : ne qualifier vos noms que si vous savez ce que vous faites. En effet les mécanismes du C++ sont là dans l'esprit du principe de moindre surprise, s'en affranchir c'est prendre des risques.
Enregistrer un commentaire