8

Вопрос по c++ – Как зарегистрировать указатель на функцию-член производного класса в базовом классе

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

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

У меня проблемы с аргументом указателя на функцию-член. Я думал, что Derived является производным от Base,this указатель должен быть автоматически приведен.

Can this be done close to what I am trying or do I need to use static member functions, void *, and static_cast?

class Base
{
protected:
    typedef void (Base::*PrepFn)( int n );
    void registerPrepFn( PrepFn fn ) {};
}

class Derived : public Base
{
    Derived() {
        registerPrepFn( &Derived::derivedPrepFn );
    };

    void derivedPrepFn( int n ) {};

}

Ошибка компилятора:

error: no matching function for call to 'Derived::registerPrepFn(void (Derived::*)(int))'
note: candidates are:                 'void Base::registerPrepFn(void (Base::*)(int))'
  • ну, я не хочу просто подавлять сообщение об ошибке. Будет ли это работать?

    от NoahR
  • Стандарт говорит следующее о таком преобразовании: «Если класс B содержит исходный член или является базовым или производным классом класса, содержащим исходный член, результирующий указатель на член указывает на исходный член. В противном случае результат приведения не определен. & Quot; Я боюсь, что такой бросок либо не выполнит то, что ОП хочет в лучшем случае, либо не даст полезную ценность в худшем случае.

    от
  • Я заблудился в спецификации, но я прототипировал идею @ jpalecek, и, похоже, она работает только с одним производным классом:ideone.com/R67eZ

    от NoahR
  • @LucDanton: & quot; Если класс B ...is a base or derived class of the class containing the original member ... & Quot ;. Это условие выполняется, если вы вызываете его с объектом динамического типа D и указатель на член D, что означает, что он делает то, что все хотят (явно указано в примечании, которое следует за вашей цитатой). Это только ломается, если член содержится в несвязанном классеB (может случиться с множественным наследованием, когда указатель наint D::* на самом делеint A::* а такжеA не имеет отношения кD)

    от
  • @NoahR: Да, это будет работать (но будьте осторожны с условием, выделенным жирным шрифтом)

    от
  • @jpalecekideone.com/QRGpt

    от R. Martinho Fernandes
  • @ R.MartinhoFernandes: Не совсем,static_cast буду работать.

    от jpalecek
  • Я не уверен, что именно ты хочешь делать. Но это, безусловно, невозможно таким образом; функция-член, определенная вDerived не может быть указано наBase::*, Возможно, если вы объясните цель высшего уровня, кто-то может предложить лучшее решение.

    от Oliver Charlesworth
  • FTR,void* а такжеstatic_cast тоже не будет работать, потому что указатель на функцию-член не является указателем (да, он ужасно назван).

    от R. Martinho Fernandes
  • Что касается статического приведения, я думал, что смогу реализовать статические функции-члены и явно обойти указатель this

    от NoahR
  • 12

    Если все

    что вам нужно, это побить сообщение об ошибке, то приведение произойдет:

    class Derived : public Base
    {
        Derived() {
            registerPrepFn( static_cast<PrepFn>(&Derived::derivedPrepFn) );
        };
    
        void derivedPrepFn( int n ) {};
    
    }
    

    Назовите это обычно сBase* p (provided it actually points to a Derived): (p->*registered)(0)

    Увидетьhttp://ideone.com/BB9oy для рабочего примера.

  • 0

    Это не разрешено с oop. Поведенческое переключение осуществляется путе

    м полиморфизации класса объекта во время создания объекта.

    Если вам нужно переключить поведение после создания объекта, вы можете изменить динамическое поведение на другой набор полиморфных классов и удерживать & quot; указатель & quot; к экземпляру класса с правильным поведением. Пожалуйста, Google "оформленный класс" шаблон программного обеспечения.