将成员函数ptr插入到映射中



EDIT从代码本身删除格式(粗体(。

编辑2在答案末尾添加修复

我在下面的代码中尝试创建静态多态性和模板类,我正试图在中的映射中插入一个派生类型成员函数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();
}

但是当insert函数调用(粗体部分(时,我遇到了Segmentation错误,这就像我在运行调试器时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>;

您的代码大致相当于:

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

process内部,有static_cast<Derived*>(this)-但b指向的base<derived>的实例是而不是实际上是derived的实例。您已经实例化了独立的base<derived>,而不是作为derived实例的一部分。您的程序从未创建过derivedderived1的实例。因此,您试图调用一个从未存在过的对象的成员函数,因此您的程序显示出未定义的行为。


甚至更精简的代码版本看起来是这样的:

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

这样一来,问题就应该更清楚了。

最新更新