通过带有模板的void指针调用析构函数

1 c++

我写了一个类来包含我的对象.代码是:

class objectPool
{
private:
    struct itemType_{uint count; void* object;};
    std::multimap< std::string,  itemType_ > pool_;

public:
    template<class T>
    bool addItem(std::string key, T*& object)
    {
        std::multimap< std::string,  itemType_ >::iterator
            i = pool_.find(key);
        if(i != pool_.end())
        {
            object = (T*)(*i).second.object;
            (*i).second.count++;
            return true;
        }
        i = pool_.insert(std::pair<std::string,itemType_>(key, (itemType_){1, NULL}));
        object = (T*)(*i).second.object;
        return false;
    }

    template<class T>
    bool removeItem(std::string key)
    {
        std::multimap< std::string,  itemType_ >::iterator
        i = pool_.find(key);
        if(i != pool_.end())
        {
            if((*i).second.count == 1)
            {
                //important to call the appropriate destructor
                delete ((T*)(*i).second.object);
                pool_.erase(i);
            }
            else
                (*i).second.count--;

            return true;
        }
        return false;
    }
};
Run Code Online (Sandbox Code Playgroud)

和测试代码:

#include "objectPool.h"
class testClass
{
public:
    ~testClass()
    {
        // I should get here at least once
        std::cout << "I am deleted teehee";
    }
};


    testClass* test;

    objectPool myPool;

    int main () {

        if(!myPool.addItem<testClass>("baba", test))
        {
            test = new testClass;
        }

        myPool.removeItem<testClass>("baba");
    }
Run Code Online (Sandbox Code Playgroud)

出于某种原因,我的测试对象的析构函数不希望被调用.第一个问题:为什么?哪里错了?

秒:我应该使用auto_ptr吗?(虽然我想避免使用模板......)

第三:有更好的( - 看)解决方案吗?(使用或不使用模板)

第四种:有没有办法通过没有模板的void指针调用构造函数(或者不知道原始类型)?

谢谢!:D抱歉我的英语很棒(不是我的母语,虽然......)

Soa*_*Box 5

您正确地将NULL存储到T*引用中,但这是对局部变量的引用.当您稍后通过调用new更新该本地时,这对存储在池中的项目没有影响.

解决这个问题的更简单方法是使用addItem函数创建对象new T.

至于你的另一个问题,一种在不知道原始类型的情况下调用析构函数的方法,就没有办法做到这一点.但是有一个技巧可以用于模板.您可以创建一个类似下面的模板函数,然后传递一个函数指针.

template<typename T>
void deleter(void *ptr) 
{
    delete static_cast<T*>(ptr);
}
Run Code Online (Sandbox Code Playgroud)

deleteter作为一个简单类型,你可以输入def并传递指针:

typedef void (*deleter_func)(void *);
Run Code Online (Sandbox Code Playgroud)

要获取指向它的指针,只需在addItem函数中执行以下操作:

deleter_func myDeleter = &deleter<T>;
Run Code Online (Sandbox Code Playgroud)

然后呢:

myDeleter(somePtr);
Run Code Online (Sandbox Code Playgroud)

删除时你不需要知道somePtr的类型,只需要保留一个指向删除器的指针.您也可以将此方法用于shared_ptr,它可以使用deleter参数.