我有一些没有成员变量的函数对象。函数对象本质上非常简单。它们都继承自unary_function<>binary_function<>。例如,几个函数对象可能是这样的:

struct key_to_hash_method_1 : public binary_function<int, int, int>
{
  int operator() (int a, int b) const { /* do something */ }
};

template <typename key_to_hash_method>
struct hash_shrink_method_1 : public binary_function<int, int, int>, public key_to_hash_method
{
  int operator() (int a, int b) const { /* do something while utilizing key_to_hash_method */ }
};

/* and more variations of these function objects */

模板类通过将这些功能对象作为模板参数作为策略来使用这些功能对象。然后,模板类从它们继承:
template <typename hash_method>
class foo : public hash_method
{
public:
/* do something while using hash_method as well as using the information provided by binary_function<> to selective compile different functions*/
};

当然,为了使示例简单,就实用性而言,上述内容可能没有多大意义。

为什么我继承而不是使用组合?只是为了避免空类占用空间。节省的空间是否很小不是问题的重点。

从上面的代码中可以看到,binary_function<int, int, int>将被继承两次,从而引起警告(在VC++ 2008中):
Warning 1   warning C4584: 'hash_shrink_method_1<key_to_hash_method>' : base-class 'std::binary_function<_Arg1,_Arg2,_Result>' is already a base-class of 'key_to_hash_method_1'    c:\visual studio 2008\projects\defaulttemplatearguments\main.cpp    12

现在,通常,在多重继承中,这可以通过虚拟继承来解决。在这种情况下,我想避免这种情况。在这种情况下我该怎么办才能删除警告?

我的直接解决方案是不继承binary_function<>,因为我假设key_to_hash_method将是binary_function。这种解决方案有点像程序员,他们无权访问包含保护或pragma once语句。是的,他可以避免两次包含 header ,但他宁愿编译器为他解决这个问题。在这种情况下,我也希望如此。

示例代码,如果您想尝试一下:
#include <functional>

using namespace std;

struct key_to_hash_method_1 : public binary_function<int, int, int>
{
  int operator() (int a, int b) const { return a + b; }
};

template <typename key_to_hash_method>
struct hash_shrink_method_1 : public binary_function<int, int, int>, public key_to_hash_method
{
  int operator() (int a, int b) const { return key_to_hash_method::operator()(1, 2) * 5; }
};

template <typename hash_method>
class foo : public hash_method
{
public:
  int test()
  {
    /* in actual code, this function selectively calls other functions
       depending on whether hash_method is unary or binary */
    return hash_method::operator()(5, 6);
  }
};

int main()
{
  foo<hash_shrink_method_1<key_to_hash_method_1> > f;
  printf("%i\n", f.test());
}

最佳答案

您的hash_shrink_method_1不需要直接从binary_function继承,因为您假设其参数类key_to_hash_method已经这样做。如果您想确定的话,可以添加一个静态断言(std::is_base_of)。尽管如果您已经拥有C++ 11,则仍然可以删除过时的binary_function

10-07 19:11
查看更多