вставка функции-члена ptr в карту - PullRequest
0 голосов
/ 24 октября 2019

РЕДАКТИРОВАТЬ удалить форматирование из самого кода (жирный шрифт).

Редактировать 2 добавил в конце ответа исправление

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

std::map<std::string,void(derived::*)()> m_func;

, а команда вставки такова:

`m_func.insert(make_pair("yaodav",&derived::HelloWorld));`

и это весь код:

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <memory>
#include <any>
#include <typeinfo>
#include <typeindex>
using namespace std;


template<class Derived>
class base
{
public:
    void clean()
    {
        cout << "I'm cleannig \n";
    }
    void process()
    {
        static_cast<Derived*>(this)->setup();
        static_cast<Derived*>(this)->run();
        static_cast<Derived*>(this)->cleanup();
    }
};


class derived : public  base<derived> 
{
    friend class base<derived>;
    void setup() {
        m_func.insert(make_pair("yaodav",&derived::HelloWorld));
        cout << "derived setup \n"; }
    void run() { cout << "derived run \n"; }
    void cleanup() { cout << "derived cleanup \n"; }
    void HelloWorld() {cout << "hwllo from derived \n"; }
    std::map<std::string,void(derived::*)()> m_func;

};


class derived1 : public base<derived1> 
{
    friend class base<derived1>;
    void setup() {cout << "derived1 setup \n"; }
    void run() { cout << "derived1 run \n"; }
    void cleanup() { cout << "derived1 cleanup \n"; }
    void HelloWorld(){}
};

template <class T>
class Y{
 public:
 std::vector<std::any> m_vec;   

};


template <typename T>
class D:public Y<T>
{
    public:
    friend class Y<T>;
    void print()
    {
        for(auto& e: Y<T>::m_vec)
        {
             if(e.type()==typeid(base<derived1>*))
            {
                try {
                    auto* r = any_cast<base<derived1>*>(e);
                    r->process();
                }
                catch(const std::bad_any_cast& e) {
                    std::cout << e.what() << '\n';
                }
            }
            else
            {
                try {
                    auto *r = any_cast<base<derived> *>(e);
                    r->process();
                }
                catch(const std::bad_any_cast& e) {
                    std::cout << e.what() << '\n';
                }
            }

        }
    } 
};


int main()
{
        base<derived>* b =  new base<derived>;
        base<derived1>* c =  new base<derived1>;

        D<derived> y;
        y.m_vec.push_back(b);
        y.m_vec.push_back(c);
        y.print();
}

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

здесь нет члена или метода с именем m_func

почему это происходит и как это исправить

Исправление

 base<derived>* b =  new derived;
 base<derived1>* c =  new derived1;

вместо

 base<derived>* b =  new base<derived>;
 base<derived1>* c =  new <derived1>;

1 Ответ

0 голосов
/ 25 октября 2019

Ваш код примерно эквивалентен этому:

base<derived>* b = new base<derived>;
b->process();

Внутри process есть static_cast<Derived*>(this) - но экземпляр base<derived>, на который указывает b, равен , а не на самом деле экземпляр derived. Вы создали base<derived> автономный экземпляр, а не часть derived экземпляра. Ваша программа никогда не создавала ни экземпляров derived, ни derived1. Таким образом, вы пытаетесь вызвать функцию-член объекта, который никогда не существовал, после чего ваша программа демонстрирует неопределенное поведение.


Еще более упрощенная версия вашего кода будет выглядеть так:

class Base{};
class Derived : public Base {
public:
  void DoSomething() {};
};

int main() {
  Base* b = new Base;
  static_cast<Derived*>(b)->DoSomethind();  // undefined behavior here
}

Таким образом, должно быть понятно, что не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...