2016-04-14 8 views
0

В основном, мой вопрос связан с поиском имен и using (http://en.cppreference.com/w/cpp/language/namespace).
Предположим, мы имеем следующие (определенно тупые) коды:Эффекты использования декларации при поиске имени для двух точно таких же имен

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? 

Поэтому моя понимающие теперь мы должны иметь оба названия видно, а затем поиск имен, должна быть некоторая двусмысленность. Но на самом деле это не так. В чем причина или, другими словами, я неправильно понимаю некоторые понятия?

+0

более прямую связь будет Http: // эн. cppreference.com/w/cpp/language/using_declaration – Cubbi

ответ

3

Стандарт имеет специальное правило для этого случая.

При использование декларации приносит имена из базового класса в производном классе сферу, функции членов и шаблонов функций члена в производном классе переопределить и/или функции членов скрыть и функцию члена шаблонов с (8.3.5), cv-qualification и ref-qualifier (если есть) в базовом классе (а не в конфликте).

([namespace.udecl]/15)

Обратите внимание, что, как обычно, вы можете заставить Base::fun называться делая d.Base::fun().

0

Ссылка вы ссылаетесь для namespace-х, вы должны вместо этого обратиться к class using-declaration, где говорится:

Если производный класс уже имеет элемент с таким же именем, список параметров, и квалификацию, член производного класса скрывает или переопределяет (не конфликтует) с членом, который вводится из базового класса.

В случае Опубликованной коды, void fun() в Base скрыт void fun() в Derived, так нет, они оба не «видны», если вы не явные, когда вы звоните fun, например:

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 

Кроме того, поскольку вы публично получили от Base, строго говоря, вам не нужна декларация using; вы бы в случае, что void fun() были protected в Base или private/protected «LY унаследовал от Base, например:

#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; 
} 

Надежда, которая может помочь