Данный:

Example.h

struct Base {
    virtual ~Def() = default;

    virtual void accept(struct DerivedVisitor* v) = 0;
};

struct Derived : Base {
    int num;
    void accept(struct DerivedVisitor* v) override;
};

struct DerivedVisitor {
    virtual void visit(Derived* d) = 0;
};

Example.cpp

#include "Example.h"

void Derived::accept(struct DerivedVisitor* v) {
    v->visit(this);
}

Скажем, я хотел создать экземпляр Derived "с нуля". Поскольку он содержит виртуальную функцию из Base , как мне получить адрес его таблицы виртуальных функций, чтобы я мог сделать что-то вроде этого:

Main.cpp

#include <iostream>
#include <memory>
#include "Example.h"

struct Visitor : DerivedVisitor {
    void visit(Derived* d) override {
        std::cout << d->num << std::endl;
    }
};

int main() {
    int num = 5;
    
    // Create Derived instance from scratch
    auto der = malloc(sizeof(Derived));
    auto derBytes = static_cast<char*>(der);
    new (derBytes) void*(/*HERE I NEED POINTER TO Derived VFT*/); // <------------- How?
    new (derBytes + sizeof(Base)) int(num);

    // Just to see that it works:
    Base* base = reinterpret_cast<Derived*>(der);
    Visitor visitor{};
    base->accept(&visitor);

    free(der);
    return 0;
}

Этот компилятор специфичен? Если это так, я использую MinGW, если кто-то знаком с ним.

0
Django 21 Июл 2020 в 03:33
4
Это похоже на проблему XY. Таблицы виртуальных функций являются деталью реализации и даже не должны существовать в реализации C++.
 – 
nanofarad
21 Июл 2020 в 03:40
Для этого нет веских причин. Чего вы ДЕЙСТВИТЕЛЬНО пытаетесь достичь?
 – 
Remy Lebeau
21 Июл 2020 в 04:08
Я пытаюсь создать синтаксический анализатор LR(1), который может анализировать любую грамматику LR(1) с учетом ее описания. Затем результат синтаксического анализа должен быть сохранен в AST, состоящем из классов для различных правил грамматики. Поскольку синтаксический анализатор является общим, он не может знать конкретные классы, составляющие AST, поскольку они генерируются в зависимости от грамматики, и поэтому ему необходимо построить AST из описания схемы памяти. После того, как память заполнена корректно, вызывающая сторона синтаксического анализатора может выполнить повторную интерпретацию на верхнем узле AST. Это идея в любом случае.
 – 
Django
21 Июл 2020 в 04:46
Однако я думаю, что нашел обходной путь. Вызывающий код знает конкретный класс AST и поэтому может отправить парсеру в качестве аргументов все указатели на виртуальные таблицы класса. Я использую виртуальные функции в AST для навигации по шаблону посетителя в программе проверки типов/интерпретаторе/компиляторе. Если есть идеи, как это можно сделать чище, буду признателен за помощь. :) @RemyLebeau
 – 
Django
21 Июл 2020 в 04:50
Где вы определяете Def?
 – 
curiousguy
25 Сен 2020 в 14:00

1 ответ

Лучший ответ

Этот компилятор специфичен?

Да, это зависит от компилятора.

В языке C ++ не существует такой вещи, как «таблица виртуальных функций». Такая таблица является деталью реализации.

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

1
eerorika 21 Июл 2020 в 03:43