使用抽象类作为unordered_map中的值

时间:2014-05-06 19:20:09

标签: c++

我无法使用抽象类作为值来正确编译抽象类。理想情况下,我想做类似以下的事情

unordered_map<string, Process_Base> func_map;

Process_Base的位置如何

//Contained in Process_Base.hpp
class Process_Base{

public:
    virtual ~Process_Base(){};
    virtual void process() const = 0;

};

和子类看起来像

#include "Process_Base.hpp"

class Process_Message : public Process_Base {

public:
    ~Process_Message(){};
    virtual void process();

};

#include <stdio.h>
#include <string.h>
#include "Process_Base.hpp"

class Process_Message{

public: 
    void process(){
        printf("%s", "Hello");
    }
};

这背后的想法是我能够将子类添加到地图中,并且有一个简单的函数可以查看键值并调用子类&#39;过程功能。

当我使用

在CentOS 5.8上编译时
g++44 -Wall -c -std=c++0x -I/usr/include -g Source.cpp

我收到以下一系列错误

In file included from /usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/bits/stl_algobase.h:66,
             from /usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/bits/char_traits.h:41,
             from /usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/string:42,
             from Source.cpp:2:
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/bits/stl_pair.h: In instantiation of ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base>’:
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/bits/stl_function.h:482:   instantiated from ‘std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> >’
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/tr1_impl/hashtable_policy.h:790:   instantiated from ‘std::__detail::_Hash_code_base<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base>, std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>’
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/tr1_impl/hashtable:137:   instantiated from ‘std::_Hashtable<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base>, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> >, std::_Select1st<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true>’
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/tr1_impl/unordered_map:48:   instantiated from ‘std::__unordered_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> >, false>’
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/tr1_impl/unordered_map:190:   instantiated from ‘std::unordered_map<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base, std::hash<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::equal_to<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base> > >’
Source.cpp:14:   instantiated from here
/usr/lib/gcc/x86_64-redhat-linux6E/4.4.6/../../../../include/c++/4.4.6/bits/stl_pair.h:73: error: cannot declare field ‘std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, Process_Base>::second’ to be of abstract type ‘Process_Base’
Process_Base.hpp:1: note:   because the following virtual functions are pure within ‘Process_Base’:
Process_Base.hpp:5: note:       virtual void Process_Base::process() const
make: *** [Source.o] Error 1

有人可以帮助我理解这些编译错误。尝试制作函数指针而不是子类的映射会更好吗?如果是这样,我将如何在Process Message等类中创建指向函数的指针映射。

1 个答案:

答案 0 :(得分:5)

抽象类不能直接实例化,但是你可以指向它们的值,它们的值最终被实例化(非抽象)子类。

class Abstract {
 public:
  virtual void Foo() = 0;
};

Abstract x;   // error
Abstract* p;  // fine

class Derived : Abstract {
 public:
  virtual void Foo() {
    printf("Hello!\n");
  }
};

p = new Derived();

// or:
Derived d;
p = &d;

因此,您也不能拥有抽象类的容器 - 只能指向抽象类。

unordered_map<string, Process_Base*> func_map;

根据您填充(或尝试填充)原始func_map的方式,使用unique_ptr代替常规指针可能会有所帮助。

unoredered_map<string, unique_ptr<Process_Base>> func_map;

通过这种方式,您可以执行func_map["foo"] = new Derived()之类的操作,而无需担心明确调用delete func_map["foo"]