2016-04-14 9 views
0

Fondamentalement, ma question est liée à la recherche de nom et using déclaration (http://en.cppreference.com/w/cpp/language/namespace).
Supposons que nous ayons les codes suivants (certainement stupide):effets de l'utilisation de déclaration sur la recherche de nom pour deux exactement les mêmes noms

class Base { 
public: 
    void fun() 
    {std::cout << "Base fun" << std::endl;} 
}; 

class Derived : public Base { 
public: 
    // Here both names "fun" are visible or not? 
    using Base::fun;//let's call this func_1 

    void fun() //let's call this func_2 
    { 
     std::cout << "Derived fun" << std::endl; 
    } 
}; 

Derived d; 
d.fun(); // This resolves to func_2, why? 

Par conséquent, mon COMPRENDRE est maintenant, nous devrions avoir les noms visibles, et pour la recherche de nom, il devrait y avoir une certaine ambiguïté. Mais en réalité ce n'est pas le cas. Quelle est la raison ou en d'autres termes, ai-je mal compris certains concepts?

+0

un lien plus direct serait http: // fr. cppreference.com/w/cpp/language/using_declaration – Cubbi

Répondre

3

La norme a une règle spéciale pour ce cas.

Lorsqu'un à l'aide-déclaration porte les noms d'une classe de base dans un champ de classe dérivée, les fonctions membres et modèles de fonction de membre de la substitution de la classe dérivée et/ou fonctions membres masquer et de la fonction de membre modèles avec le même nom, liste de types de paramètres (8.3.5), qualification-cv et qualificatif-réf (le cas échéant) dans une classe de base (plutôt que de conflit).

([namespace.udecl]/15)

Notez que comme d'habitude, vous pouvez forcer Base::fun à appeler en faisant d.Base::fun().

0

Le lien que vous faites référence est pour namespace « s, vous devriez plutôt se référer à la class using-declaration où il est dit:

Si la classe dérivée a déjà membre du même nom, la liste des paramètres et qualifications, le membre de classe dérivé cache ou remplace (n'est pas en conflit avec) le membre qui est introduit à partir de la classe de base.

Dans le cas de votre code affiché, void fun() dans Base est caché par void fun() dans Derived, donc pas, ils ne sont pas à la fois « visible », sauf si vous êtes explicite lorsque vous appelez fun, par exemple:

class Base { 
    public: 
     void fun() { std::cout << "base" << std::endl; } 
}; 

class Derived : public Base { 
    public: 
     using Base::fun; 
     void fun() { std::cout << "derived" << std::endl; } 
}; 

Derived d; 
d.fun(); // name lookup calls Derived::fun 
d.Base::fun(); // explicitly call Base::fun 

En outre, puisque vous avez dérivé publiquement de Base, à proprement parler, vous n'avez pas besoin de la déclaration using; vous le feriez dans l'instance void fun() étaient protected dans Base ou vous private/protected « ment hérité de Base, par exemple:

#include <iostream> 

class Base { 
    public: 
     void fun() { std::cout << "base" << std::endl; } 
    protected: 
     void fun2() { std::cout << "base2" << std::endl; } 
}; 

// class default is private 
class Private : Base { 
    public: 
     // fun() won't be accessible since private inheritance and no using 
     // fun2 can now be accessed directly 
     using Base::fun2; 
}; 

class Public : public Base { 
    public: 
     // fun is already public 
     using Base::fun2; // bring into scope 
}; 

class Derived : public Base { 
    public: 
     using Base::fun; 
     using Base::fun2; 

     // overriden method fun, no conflict, choose this method if type is Derived 
     void fun() { std::cout << "derived" << std::endl; } 
}; 

int main(int argc, char* argv[]) 
{ 
    Private p; 
    Public u; 
    Derived d; 

    // generates a compiler error since Base is privately inherited 
    //p.fun(); 
    p.fun2(); // OK, output: base2 

    u.fun(); // OK, output: base 
    u.fun2(); // OK, output: base2 

    // use Derived::fun since override 
    d.fun(); // OK, output: derived 
    d.Base::fun(); // OK, output: base 
    d.fun2(); // OK, output: base2 

    return 0; 
} 

espoir qui peut aider