2

我一直在试图弄清楚如何正确地将函数与 id 配对。到目前为止,我一直在做的是一种 C 方式:

#include <iostream>

void PrintA();
void PrintB();

struct Function
{
    int id;
    void (*function)();
};

static const Function functions[] =
{
    {1, PrintA},
    {2, PrintB},
    {0, 0}
};

void PrintA()
{
    std::cout << "A" << std::endl;
};

void PrintB()
{
    std::cout << "B" << std::endl;
};

int main()
{
    int id = 1;

    for(int i = 0; functions[i].function != 0 ; i++)
    {
        if(functions[i].id == id)
        {
            functions[i].function();
        }
    }
}

我正在尝试使用 C++ 中的仿函数来实现相同的功能。我想我需要使用继承才能将不同的函数存储在同一个数组中,这意味着我还需要对数组使用指针以防止切片。以下方法是正确的方法吗?还有其他选择吗?

还有比我如何调用操作员更简单的版本吗?

#include <iostream>
#include <memory>

class Base
{
public:
    virtual void operator()() = 0;
};

class PrintA : public Base
{
public:
    void operator()();
};

void PrintA::operator()()
{
    std::cout << "A" << std::endl;
}

class PrintB : public Base
{
public:
    void operator()();
};

void PrintB::operator()()
{
    std::cout << "B" << std::endl;
}

struct Functor
{
    int id;
    std::shared_ptr<Base> function;
};

static Functor functors[] = 
{
    {1, std::shared_ptr<Base>(new PrintA)},
    {2, std::shared_ptr<Base>(new PrintB)},
    {0, 0}
};

int main()
{
    int id = 2;

    for(int i = 0; functors[i].function != 0 ; i++)
    {
        if(functors[i].id == id)
        {
            functors[i].function->operator()();
        }
    }
}

编辑:我必须使用相当旧的 GCC 版本,因此无法使用 c++11 功能。不过,Boost 是可用的。我想 std::map 是个好主意,但我真正要问的是(并没有真正说清楚)有没有比 shared_ptr 更好的方法来存储函数。我想 std::function/boost::function 方式是这样做的方式。

4

2 回答 2

4

在 C++11(或 Boost,如果你被困在过去)中,这种类型擦除function在包装器中是可用的;并且总是map执行基于 ID 的查找。所以你的例子很简单:

#include <map>
#include <functional>
#include <iostream>

// Note: This will be a lot messier if you're stuck with a pre-2011 compiler.
// You'll need to define the functors (or functions) separately, and either
// initialise the map with the result of a function call (possibly using
// Boost.Assign), or write some code somewhere else to populate it.
//
// Or use an array, with lookup code like your C implementation.
std::map<int, std::function<void()>> functors {
    {1, [](){std::cout << "A" << std::endl;}},
    {2, [](){std::cout << "B" << std::endl;}}
};

int main() {
    functors[2]();
}

如评论中所述,如果实际情况与示例一样简单,则可以使用函数指针而不是function(如果愿意,仍然可以使用 lambda 初始化它)和数组(由 id 索引)而不是地图。我的示例假设您想要一个更通用的解决方案,将任意值映射到任意函子。

于 2013-08-27T12:36:00.947 回答
2

简单的:

#include <functional>
#include <iostream>
#include <vector>

void sayA() { std::cout << "A" << std::endl; }
void sayB() { std::cout << "B" << std::endl; }
struct Foo
{
  explicit Foo(int i) : i_(i) {}
  void operator()() const { std::cout << "foo " << i_<< "!" << std::endl; }
  int i_;
};

std::vector<std::function<void()>> funcs{ sayA, sayB, Foo(42) };

int main()
{
  for (const auto& f : funcs) f();
}
于 2013-08-27T12:38:45.620 回答