С++ Сокрытие имен при наследовании

При наследовании классов возможны приколы с видимостью унаследованных методов и полей. Если при открытом наследовании в классе потомке переопределен метод родительского класса, то компилятором будет использоваться метод потомка:

class Base {
public:
    virtual void func1();
    ...
}
class Derived: public Base {
public:
    virtual void func1(); // переопределение Base::func1()
    ...
}
...
Derived d;
d.func1(); // вызовется  Derived::func1()

И в данном случае, когда не используется указатели или ссылки на экземпляр, а работаем конкретно с бъектом не имеет значения virtual они или нет!

Если в классе-родителе переопределяемый метод имеет перегруженные варианты, то по-умолчанию они не будут доступны в классе-потомке!

И это как бы нормально, но если в классе-родителе переопределяемый метод имеет перегруженные варианты, то в нашем случае в классе потомке мы их уже не увидим:

class Base {
public:
    virtual void func1();
    virtual void func1(int);
    ...
}

class Derived: public Base {
public:
    virtual void func1(); // переопределение Base::func1()
    ...
}
...
Derived d;
d.func1(); // вызовется  Derived::func1()
d.func1(777); // Будет ошибка !!!

Это происходит потому что компилятор найдя в Derived имя func1 - дальше и не пойдет, но в классе Derived нет метода подходящего для func1(int) о чем компилятор ним и сообщит:

error: no matching function for call to 'Derived::func1(int&)'

Лечится такое инструкцией using:

class Base
{
public:
    virtual void func1();
    virtual void func1(int);
    ...
}
class Derived: public Base
{
public:
    using Base::func1;  // теперь доступны все варианты метода func1 !!!
    virtual void func1(); // переопределение Base::func1()
    ...
}
...
Derived d;
d.func1(); // вызовется  Derived::func1()
d.func1(777); // вызовется  Base::func1(int)

Инструкция: using КлассРодитель::метод; введет в область видимости класса-потомка все варианты запрошенного метода, в том числе и перегруженные.

Для закрытого наследования использование using может не подойти т.к. откроет все перегрузки указанного метода. Когда это нужно? Допустим нам нужно в классе-потомке, в открытом доступе иметь ТОЛЬКО метод В::mf1(int)

class A
{
public:
    virtual void mf1();
    virtual void mf1(int);
    virtual void mf1(double);
};

class B: private A
{
public:
    // Не прокатит! Это откроет все!
    // Наружу будут торчать:
    // B::mf1() и B::mf1(int) и B::mf1(double) !!!
    using A::mf1;
};

В данном случае целесообразно использовать методы-обертки:

class A
{
public:
    virtual void mf1();
    virtual void mf1(int);
    virtual void mf1(double);
};

class B: private A
{
public:
    // "пробрасываем" конкретно mf1(int) 
    // Остальные:  mf1() и mf1(double) остаются не доступными!
    virtual void mf1(int x)
    { A::mf1(x); }
};