Передача указателя на метод класса в конструктор вложенного класса

233
07 августа 2018, 10:00

У меня есть класс, внутри которого объявлен объект другого класса (композиция). Первый содержит метод, указатель на который нужно передать в конструктор второго класса. Это получилось. Как потом вызвать метод по указателю? В реальности внутри класса объявляются несколько объектов разных классов. Есть одна функция которую нужно использовать в некоторых из внутренних классов. Поэтому и пытаюсь понять как это сделать. Пробую передать указатель на нее.

заголовочный файл

class CharScreen; // класс внутри которого будет объявлен объект Loader
class Loader 
{
    private:
        void (CharScreen::* Conv)(uint8_t index); // указатель на метод
    public:
        Loader(void (CharScreen::* Convertor)(uint8_t index));
        void CalculateMenuSize(); // метод внутри которого нужно сделать 
                                  // вызов, переданного в конструктор 
                                  // метода, по указателю
};
class CharScreen
{
    private:
        Loader Loader; // объявляю объект Loader
    public:
        CharScreen();
        void ConvertVar(uint8_t index); // тот самый метод, который нужно 
                                        // передать в конструктор Loader
};

cpp

Loader::Loader(void (CharScreen::* Convertor)(uint8_t index)):
{
    Conv = Convertor; // присваиваю объявленному в заголовке указателю, 
                      // преданный в конструктор параметр-указатель на метод
}
void Loader::CalculateMenuSize()
{
    (*Conv)(1); // вот здесь возникает проблема "operand of "*" must be a 
                // pointer"
}
CharScreen::CharScreen():
Loader(&CharScreen::ConvertVar)
{
    Loader.CalculateMenuSize();
}
void CharScreen::ConvertVar(uint8_t index)
{
}
Answer 1

Объявление члена класса

    Loader Loader;

недопустимо. Либо

    class Loader Loader;

либо сделайте так, чтобы имя поля не совпадало с именем класса. (На самом деле стандарт в этом вопросе как-то неоднозначен...)

Ну так а для какого именно объекта класса CharScreen вы собрались вызывать этот метод? Нет объекта - нечего и вызывать.

Мое гадание на кофейной гуще подсказывает мне, что вы хотите вызвать этот метод из экземпляра класса Loader именно для того объекта CharScreen, который содержит в себе этот экземпляр класса Loader. В С++ нет готовых инструментов для перехода от содержимого объекта к содержащему объекту. Тут могут помочь "хаки", типа известного container_of

#define container_of(ptr, type, member)\
  ((type *) ((char *) ptr - offsetof(type, member)));
void Loader::CalculateMenuSize()
{
  CharScreen *owner = container_of(this, CharScreen, Loader);
  (owner->*Conv)(1);
}

но здесь придется сражаться с правами доступа.

Лучше было бы просто воспользоваться std::function<> для хранения "указателя" на метод, а правильный экземпляр такого std::function<> формировать в конструирующем коде (при помощи std::bind или еще как).

Answer 2

В CalculateMenuSize аргументом нужно передать ссылку на объект CharScreen если объектов CharScreen много экземпляров, чтоб не было недоразумений. Или если он один, тогда метод ConvertVar сделайте static, тогда можно не использовать конкретный объект.

void Loader::CalculateMenuSize(CharScreen & obj) {
    (obj.*Conv)(1); }

или

class Loader {
  void (*Stat)(uint8_t);};
class CharScreen {
  static void ConvertVar(uint8_t index); };
void Loader::CalculateMenuSize() {
    Stat(1); }
READ ALSO
Windows form построение графиков

Windows form построение графиков

Здравствуйте хотел бы узнать как реализовать построение синусоиды в плоскости XYZ в windows form на C++ ?

295
Расстановка знаков между числами

Расстановка знаков между числами

Даны N чиселНужно расставить + и * между ними и получить максимум

240
Как переопределить сигнал в qt?

Как переопределить сигнал в qt?

У меня вопрос как переопределить сигнал в Qt?

268
Не выполняется служба

Не выполняется служба

Когда запускаешь просто exe, все работаетКогда запускаешь службу, пишет только первую часть, цикл while (!pRstAuthors->EndOfFile) не выполняется

197