LinkedIn SDK выдает ошибку аутентификации

Судя по формулировке вашего вопроса (вы использовали слово «скрыть»), вы уже знаете, что здесь происходит. Это явление называется «сокрытие имени». По какой-то причине каждый раз, когда кто-то задает вопрос о , почему происходит скрытие имени , люди, которые отвечают, говорят, что это называется «скрытие имени» и объясняют, как это работает (что вы, вероятно, уже знаете), или объясните как его переопределить (о котором вы никогда не спрашивали), но, похоже, никто не заботится об актуальном вопросе «почему».

Решение, обоснование скрытия имени, т.е. , почему , он фактически был разработан в C ++, заключается в том, чтобы избежать определенного противоречивого, непредвиденного и потенциально опасного поведения, которое может иметь место, если унаследованный набор перегруженных функций был позволен смешиваться с текущим набором перегрузок в данном классе. Вероятно, вы знаете, что в C + + перегрузка разрешает работу, выбирая наилучшую функцию из набора кандидатов. Это делается путем сопоставления типов аргументов с типами параметров. Правила сопоставления иногда могут быть сложными и часто приводят к результатам, которые могут быть восприняты нелогично неподготовленным пользователем. Добавление новых функций в набор ранее существующих может привести к довольно резкому сдвигу результатов разрешения перегрузки.

Например, предположим, что базовый класс B имеет функцию-член foo, которая принимает параметр типа void *, и все вызовы foo(NULL) разрешены B::foo(void *). Предположим, что скрытие имени отсутствует, и этот B::foo(void *) отображается во многих разных классах, спускающихся с B. Однако, скажем, в некотором [косвенном, удаленном] потомке D класса B определена функция foo(int). Теперь, без скрытия имени D, оба foo(void *) и foo(int) видны и участвуют в разрешении перегрузки. Какую функцию будут выполнять вызовы foo(NULL), если они сделаны через объект типа D? Они разрешат D::foo(int), поскольку int является лучшим совпадением для интегрального нуля (т. Е. NULL), чем любой тип указателя. Таким образом, по всей иерархии обращается к foo(NULL) к одной функции, а в D (и под) они внезапно решаются на другую.

Другой пример приведен в . Дизайн и эволюция C ++ , стр. 77:

class Base {
    int x;
public:
    virtual void copy(Base* p) { x = p-> x; }
};

class Derived{
    int xx;
public:
    virtual void copy(Derived* p) { xx = p->xx; Base::copy(p); }
};

void f(Base a, Derived b)
{
    a.copy(&b); // ok: copy Base part of b
    b.copy(&a); // error: copy(Base*) is hidden by copy(Derived*)
}

Без этого правила состояние b будет частично обновлено, что приводит к разрезанию.

Такое поведение считалось нежелательным при разработке языка. В качестве лучшего подхода было решено следовать спецификации «сокрытие имени», что означает, что каждый класс начинается с «чистого листа» в отношении каждого имени метода, которое он объявляет. Чтобы переопределить это поведение, пользователю необходимо выполнить явное действие: изначально переобучение унаследованных методов (в настоящее время устарело), ​​теперь явное использование использования-объявления.

Как вы правильно заметили в вашем исходном сообщении (я имею в виду замечание «Не полиморфное»), это поведение можно рассматривать как нарушение отношений IS-A между классами. Это правда, но, видимо, тогда было решено, что в конечном итоге сокрытие имен окажется меньшим злом.

0
задан Kartika Vij 19 March 2019 в 09:55
поделиться