К C++ “это” не соответствует методу объекта, обратились

Мне удалось найти обходной путь, который заключается в передаче dict.items () параметру pd.DataFrame.

Мой код ниже:

df = pd.DataFrame(dict_of_files_local.items(), columns=['Timestamp', 'Filename'])

Теперь выводит следующее:

            Timestamp                           Filename
0 2019-02-07 09:11:39  C:\csv\myfile_20190207_091139_...
1 2019-02-08 03:08:11  C:\csv\myfile_20190208_030811_...
6
задан andygeers 21 March 2009 в 12:33
поделиться

6 ответов

Я полагаю, что Вы просто видите артефакт способа, которым компилятор создает vtables. Я подозреваю, что CMotion имеет виртуальные функции сами по себе, и таким образом Вы заканчиваете со смещениями в производном объекте для получения до базового объекта. Таким образом, различные указатели.

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

10
ответ дан 8 December 2019 в 12:22
поделиться

Класс CMotion, получает некоторый другой класс также, который содержит виртуальную функцию? Я нашел, что этот указатель не изменяется с кодом, который Вы отправили, однако он изменяется, если у Вас есть иерархия что-то вроде этого:

class Test
{
public:
    virtual void f()
    {

    }
};

class CWaitable 
{
public:
    void WakeWaiters() const
    {
        const CWaitable* p = this;
    }
};

class CMotion : public CWaitable, Test
{ };


class CMotionWalk : public CMotion
{
public:
 };



void AnnoyingFunctionThatBreaks(CMotion* pMotion)
{
    pMotion->WakeWaiters();
}

Я полагаю, что это из-за множественного наследования для класса CMotion и vtable указателя в CMotion, который указывает на Тест:: f ()

6
ответ дан 8 December 2019 в 12:22
поделиться

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

2
ответ дан 8 December 2019 в 12:22
поделиться

Необходимо отправить некоторый фактический код. Значения для указателей в следующем как ожидалось - т.е. они - то же:

#include <iostream>
using namespace std;

struct A {
    char x[100];
    void pt() {
        cout << "In A::pt this = " << this << endl;
    }
};

struct B : public A { 
    char z[100];
};

void f( A * a ) {
    cout << "In f ptr = " << a << endl;
    a->pt();
}

int main() {
    B b;
    f( &b );
}
0
ответ дан 8 December 2019 в 12:22
поделиться

Я думаю, что могу объяснить этого... существует лучшее объяснение где-нибудь в одном из книг Meyer's или Sutter, но я не испытывал желание искать. Я верю тому, что Вы видите, последствие того, как виртуальные функции реализованы (vtables) и, "Вы не платите за него, пока Вы не используете его" природа C++.

Если нет никаких виртуальных используемых методов, то указатель на объект указывает на данные объекта. Как только виртуальный метод представлен, компилятор вставляет виртуальную (vtable) справочную таблицу, и указатель указывает на это вместо этого. Я, вероятно, пропускаю что-то (и мой мозг еще не работает), так как я не мог заставить это происходить, пока я не вставил элемент данных в базовый класс. Если базовый класс имеет элемент данных, и первый дочерний класс имеет виртуальное, то смещения отличаются размером vtable (4 на моем компиляторе). Вот пример, который показывает это ясно:

template <typename T>
void displayAddress(char const* meth, T const* ptr) {
    std::printf("%s - this = %08lx\n", static_cast<unsigned long>(ptr));
    std::printf("%s - typeid(T).name() %s\n", typeid(T).name());
    std::printf("%s - typeid(*ptr).name() %s\n", typeid(*ptr).name());
}

struct A {
    char byte;
    void f() { displayAddress("A::f", this); }
};
struct B: A {
    virtual void v() { displayAddress("B::v", this); }
    virtual void x() { displayAddress("B::x", this); }
};
struct C: B {
    virtual void v() { displayAddress("C::v", this); }
};

int main() {
   A aObj;
   B bObj;
   C cObj;

   std::printf("aObj:\n");
   aObj.f();

   std::printf("\nbObj:\n");
   bObj.f();
   bObj.v();
   bObj.x();

   std::printf("\ncObj:\n");
   cObj.f();
   cObj.v();
   cObj.x();

   return 0;
}

Выполнение этого на моей машине (MacBook Pro) печатает следующее:

aObj:
A::f - this = bffff93f
A::f - typeid(T)::name() = 1A
A::f - typeid(*ptr)::name() = 1A

bObj:
A::f - this = bffff938
A::f - typeid(T)::name() = 1A
A::f - typeid(*ptr)::name() = 1A
B::v - this = bffff934
B::v - typeid(T)::name() = 1B
B::v - typeid(*ptr)::name() = 1B
B::x - this = bffff934
B::x - typeid(T)::name() = 1B
B::x - typeid(*ptr)::name() = 1B

cObj:
A::f - this = bffff930
A::f - typeid(T)::name() = 1A
A::f - typeid(*ptr)::name() = 1A
C::v - this = bffff92c
C::v - typeid(T)::name() = 1C
C::v - typeid(*ptr)::name() = 1C
B::x - this = bffff92c
B::x - typeid(T)::name() = 1B
B::x - typeid(*ptr)::name() = 1C

Интересная вещь - это оба bObj и cObj покажите изменение адреса как между вызывающими методами для A и B или C. Различие - это B содержит виртуальный метод. Это позволяет компилятору вставлять дополнительную таблицу, необходимую для реализации функциональной виртуализации. Другая интересная вещь, которую показывает эта программа, является этим typeid(T) и typeid(*ptr) отличается в B::x когда это называют фактически. Можно также видеть, что размер увеличивает использование sizeof как только виртуальная таблица вставляется.

В Вашем случае, как только Вы сделали CWaitable::WakeWaiters виртуальный, vtable вставляется, и это на самом деле обращает внимание на реальный тип объекта, а также вставки бухгалтерских необходимых структур. Это вызывает смещение к основе объекта отличаться. Мне действительно жаль, что я не мог найти ссылку, которая описывает мифическое расположение памяти и почему адрес объекта зависит от типа, что это интерпретируется как тогда, когда наследование смешано в забаву.

Общее правило: (и Вы услышали это прежде), базовые классы всегда имеют виртуальные деструкторы. Это поможет устранить мало неожиданностей как это.

1
ответ дан 8 December 2019 в 12:22
поделиться

Я не могу объяснить, почему это работает, но объявление CWaitable:: WakeWaiters как виртуальный устраняет проблему

0
ответ дан 8 December 2019 в 12:22
поделиться
Другие вопросы по тегам:

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