Коли ви телефонуєте a.foo();
, компілятор проходить роздільну здатність перевантаження, щоб знайти найкращу функцію, яку слід використовувати. Коли він будує встановлений набір перевантажень
void foo() const
і
void foo()
Тепер, оскільки a
це не так const
, найкраща відповідність має non-const версія, тому компілятор вибирає void foo()
. Потім встановлюються обмеження доступу, і ви отримуєте помилку компілятора, оскільки void foo()
є приватною.
Пам'ятайте, що в роздільній здатності перевантаження це не "знайти найкращу функціональну функцію". Це "знайти найкращу функцію та спробувати її використати". Якщо він не може через обмеження доступу або видалений, ви отримуєте помилку компілятора.
Іншими словами, чому перед контролем доступу виникає дозвіл на перевантаження?
Що ж, давайте подивимось:
struct Base
{
void foo() { std::cout << "Base\n"; }
};
struct Derived : Base
{
void foo() { std::cout << "Derived\n"; }
};
struct Foo
{
void foo(Base * b) { b->foo(); }
private:
void foo(Derived * d) { d->foo(); }
};
int main()
{
Derived d;
Foo f;
f.foo(&d);
}
Тепер скажемо, що насправді я не мав намір робити void foo(Derived * d)
приватним. Якщо контроль доступу з’явився першим, ця програма збиралася б і запускалася та Base
була б надрукована. Це може бути дуже важко знайти у великій базі коду. Оскільки контроль доступу приходить після вирішення перевантаження, я отримую гарну помилку компілятора, яка повідомляє мені функцію, яку я хочу, щоб її викликали, не можна викликати, і я можу знайти помилку набагато простіше.