C ++中的类查找

时间:2014-11-03 19:55:39

标签: c++ class

问题:

我有一组像Database一样的类。我需要根据他们的操作码解包某些响应。

eq:操作码:01          要求:A

从请求A解压缩响应,我创建了一个类A.同样,我没有类。

我需要根据操作码将byteArray解压缩到其中一个类中。

C ++中是否有任何机制可以实现某种映射,我可以在其中查找操作码并选择要解压缩的类/响应

PS:非常喜欢可读的解决方案和一些解释。

我对JAVA知之甚少,但在JAVA中,我猜我们有使用对象类型,类类型等的机制。

由于

3 个答案:

答案 0 :(得分:5)

您可以实现工厂:从操作码(作为整数/枚举),类名(作为字符串)等映射到动态实例化类的函数:

enum Opcode {
    OpFoo,
    OpBar,
    OpQux,
};

// this should be a pure virtual ("abstract") base class
class Operation {
    // ...
};

class OperationFoo: public Operation {
    // this should be a non-abstract derived class
};

class OperationBar: public Operation {
    // this should be a non-abstract derived class too
};

std::unordered_map<Opcode, std::function<Operation *()>> factory {
    { OpFoo, []() { return new OperationFoo; } }
    { OpBar, []() { return new OperationBar; } }
    { OpQux, []() { return new OperationQux; } }
};

Opcode opc = ... // whatever
Operation *objectOfDynamicClass = factory[opc]();

作为奖励,您可以(并且可能应该)使用智能指针(std::unique_ptrstd::shared_ptr)而不是原始指针在工厂lambda函数的返回类型和您使用的其他位置抽象类。

答案 1 :(得分:2)

您应该了解C ++中的类仅在编译时存在。在运行时,您只有vtables,可能还有RTTI,但这些类已被遗忘。 (这在Java中是不同的,类在运行时存在并且为JVMclass loaders所知。)

您可能想要使用factory pattern。例如,您可能(在C++11中)有一个全局映射,将某些名称(或您的操作码)与工厂函数构建实例相关联。 this answer提供了一些示例代码。

在某些操作系统上(或使用POCO等某些库),您可以使用dynamic loading&amp; plugin设施dlopen(3)等设施Posix上的dlsym(例如Linux)。请注意,dlsym可以通过其unmangled)名称访问extern "C"函数。另请参阅this

答案 2 :(得分:0)

一个非常模板化的解决方案,使用如下:

class A {virtual ~A() = 0;};
inline A::~A() = default;

class B : A {};
class C : A {};
class D : B {};

// Define the factory
DEFINE_FACTORY(A, B, C, D)

// Want the factory?
factory<A> a_factory;
A* ap = a_factory(1, 0, 1, 2, 3); // Creates a C, passing 0,1,2,3 to the ctor
delete ap;
// Or directly?
make<std::unique_ptr>(1,0,1,2,3); // Creates a C, passing 0,1,2,3 to the ctor
// Immediately destroyed because the `std::unique_ptr` was not saved.

这里的模板代码使其成为可能:

#include <utility>
#include <memory>
#include <exception>

template<class I, class... X> struct factory_base {
    template<class... ARGS> inline I* operator()(int i, ARGS&&... args) {
        return make(i, std::forward<ARGS>(args)...);
    }
    template<class... ARGS> using maker_t = I*(*)(ARGS...);
    template<class... ARGS> static I* make(int i, ARGS&&... args) {
        constexpr maker_t<ARGS...> maker[] = {make_helper<X, ARGS...>()...};
        if(i < sizeof...(X) && maker[i])
            return maker[i](std::forward<ARGS>(args)...);
        throw std::invalid_argument("The selected class cannot be constructed thus.");
    }
    template<class Y, class... ARGS> inline static constexpr maker_t<ARGS...>
    make_helper(...) {return nullptr;}
    template<class Y, class... ARGS> inline static constexpr auto make_helper()
    -> decltype(new Y(std::declval<ARGS>()...), maker_t<ARGS...>(0))
    {return static_cast<maker_t<ARGS...>>(
        [](ARGS&&... args){return new Y(std::forward<ARGS>(args)...);});}
};
template<class I> class factory;

#define DEFINE_FACTORY(A, ...) template<> struct factory<A> : \
    factory_base<A, __VA_ARG__> {}

template<class I, class... ARGS> std::unique_ptr<I> make(ARGS&&... args) {
    return factory<I>()(std::forward<ARGS>(args)...);
}