Вызов перегруженной функции базового класса в AVR Studio [duplicate]

Вы можете использовать метод fillna в DataFrame и указать метод как ffill (форвардная заливка):

>>> df = pd.DataFrame([[1, 2, 3], [4, None, None], [None, None, 9]])
>>> df.fillna(method='ffill')
   0  1  2
0  1  2  3
1  4  2  3
2  4  2  9

Этот метод ...

распространять [s] последнее действительное наблюдение вперед к следующему действительному

blockquote>

. Чтобы перейти в другую сторону, существует также метод bfill.

Этот метод не изменяет DataFrame inplace - вам нужно будет перестроить возвращаемый DataFrame в переменную или указать inplace=True:

df.fillna(method='ffill', inplace=True)

191
задан Rob Kennedy 27 October 2009 в 06:40
поделиться

4 ответа

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

Решение, обоснование скрытия имени, т.е. , почему , он фактически был разработан в 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 между классами. Это правда, но, видимо, тогда было решено, что в конечном итоге сокрытие имен окажется меньшим злом.

359
ответ дан Jason 21 August 2018 в 13:39
поделиться
  • 1
    Да, это реальный ответ на вопрос. Спасибо. Мне тоже было любопытно. – Omnifarious 27 October 2009 в 07:55
  • 2
    Отличный ответ! Также, как практический вопрос, компиляция, вероятно, будет намного медленнее, если поиск по именам должен был пройти весь путь до вершины каждый раз. – Drew Hall 27 October 2009 в 12:24
  • 3
    (Старый ответ, я знаю.) Теперь nullptr я бы возражал против вашего примера, сказав «если вы хотите вызвать версию void*, вы должны использовать тип указателя & quot ;. Есть ли другой пример, где это может быть плохо? – GManNickG 17 May 2011 в 20:26
  • 4
    Имя, скрывающееся, на самом деле не злое. & Quot; is-a & quot; отношения все еще существуют и доступны через базовый интерфейс. Поэтому, возможно, d->foo() не получит вас «Is-a Base», но static_cast<Base*>(d)->foo() будет , включая динамическую отправку. – Kerrek SB 9 January 2014 в 15:36
  • 5
    Этот ответ бесполезен, потому что приведенный пример ведет себя так же или не скрывает: D :: foo (int) будет вызван либо потому, что он лучше соответствует, либо потому, что он скрыл B: foo (int). – Richard Wolf 8 July 2014 в 04:06

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

В этом случае gogo(int*) найден (один) в области Derived класса, и поскольку стандартного преобразования нет от int до int *, поиск не выполняется.

Решение состоит в том, чтобы принести объявления Base с помощью объявления using в классе Derived:

using Base::gogo;

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

39
ответ дан Drew Hall 21 August 2018 в 13:39
поделиться
  • 1
    Но почемуyyy ????? – Matt Joiner 8 July 2014 в 04:58
  • 2
    OP: «Почему переопределенная функция в производном классе скрывает другие перегрузки базового класса? & Quot; Этот ответ: «Потому что это так». – Richard Wolf 8 July 2014 в 04:58

Это «По дизайну». В разрешении перегрузки C ++ для этого типа метода работает следующим образом.

  • Начиная с типа ссылки и затем переходя к базовому типу, найдите первый тип, который имеет метод с именем «gogo «
  • Учитывая только методы с именем« gogo »в этом типе, найдите соответствующую перегрузку

. Поскольку Derived не имеет соответствующей функции с именем« gogo », разрешение перегрузки выходит из строя.

13
ответ дан JaredPar 21 August 2018 в 13:39
поделиться

Скрытие имени имеет смысл, потому что оно предотвращает двусмысленности в разрешении имен.

Рассмотрим этот код:

class Base
{
public:
    void func (float x) { ... }
}

class Derived: public Base
{
public:
    void func (double x) { ... }
}

Derived dobj;

Если Base::func(float) не был скрыт Derived::func(double) в Derived, мы вызывали бы функцию базового класса при вызове dobj.func(0.f), хотя поплавок можно было бы продвигать до двойного.

Ссылка: http://bastian.rieck.ru/blog/posts/ 2016 / name_hiding_cxx /

2
ответ дан Sandeep Singh 21 August 2018 в 13:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: