使用抽象类作为unordered_map中的值

JME*_*JME 3 c++

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

unordered_map<string, Process_Base> func_map;
Run Code Online (Sandbox Code Playgroud)

Process_Base的样子

//Contained in Process_Base.hpp
class Process_Base{

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

};
Run Code Online (Sandbox Code Playgroud)

和子类看起来像

#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");
    }
};
Run Code Online (Sandbox Code Playgroud)

这背后的想法是我能够在地图中添加子类,并有一个简单的函数,它将查看一个键值并调用子类的进程函数.

当我在CentOS 5.8上编译时使用

g++44 -Wall -c -std=c++0x -I/usr/include -g Source.cpp
Run Code Online (Sandbox Code Playgroud)

我得到以下一系列错误

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
Run Code Online (Sandbox Code Playgroud)

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

Ale*_*lec 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;
Run Code Online (Sandbox Code Playgroud)

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

unordered_map<string, Process_Base*> func_map;
Run Code Online (Sandbox Code Playgroud)

根据您填充(或尝试填充)原始文件的方式func_map,使用unique_ptrs而不是常规指针可能是有益的.

unoredered_map<string, unique_ptr<Process_Base>> func_map;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以执行以下操作,func_map["foo"] = new Derived()而不必担心显式调用delete func_map["foo"].

  • 或std :: unique_ptr,它在C ++ 11中,并保证明确的所有权语义。 (2认同)