获取重载静态函数的地址

时间:2012-08-31 18:03:25

标签: c++

  

可能重复:
  how to specify a pointer to an overloaded function?

我有一个库,其类定义为:

struct ClassA
{
    static ClassA foo(long);
    static ClassA foo(double);
}

我需要获取这两个函数的地址。我目前正在尝试的代码给出错误C2440:无法从'overloaded-function'转换为'...'

ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

我认为它们可能是静态的,但在返回类型之前或之后放置静态会产生相同的错误。

3 个答案:

答案 0 :(得分:5)

函数重载的事实并不真正相关。这里真正的问题是函数指针和成员函数指针之间的区别。我将在不重载的情况下运行一些示例。

解决方案:删除static,以便将它们定义为成员函数。或者用ns::ClassA::*ClassA_foo1替换*ClassA_foo1。我想你想要后者。 (但我实际上建议您使用typedef,正如其他人已经建议的那样。)

考虑这两个:

namespace ns {
struct ClassA
{
    static ClassA foo(long);
};
}

namespace ns {
struct ClassA
{
    ClassA foo(long);
};
}

在前一种情况下,foo是static因此是一个典型的函数,可以存储在函数指针中:

ns::ClassA (ClassA_foo1)(long) = &ns::ClassA::foo;

如果你删除了static,那么不再一个函数,它就是一个成员函数。指向成员函数的指针与指向函数的指针不同,它们必须使用一个对象来执行,该对象将是调用该方法的this对象。

函数指针的类型包括返回值的类型和参数的类型。但是指向成员函数的指针类型还必须包含this对象的类型 - 您不希望能够在类型对象上从Circle运行方法BankAccount

声明指向函数的指针:

 ReturnType (*variable_name) (PARAM1, PARAM2)

声明指向成员函数的指针:

 ReturnType (ThisObjectType::*variable_name) (PARAM1, PARAM2)

最后一行是有趣的。乍一看,您可能认为R (A::*v) (P1,P2)声明了一个正常的函数指针,并将结果变量v放入A范围。但事实并非如此。相反,它定义了一个指向成员的指针函数,该函数对A类型的对象进行操作。

答案 1 :(得分:4)

您正在观察的问题与函数重载的事实完全无关。对于非重载函数,您会得到相同的错误。

静态成员函数具有普通函数类型。同时,您试图将它们解释为成员函数类型的函数。这会导致编译器向您报告指针类型不匹配。这是一个简单的例子,由于同样的原因无法编译

struct S {
  static void foo();
};
...
void (S::*p)() = &S::foo; // ERROR, pointer type mismatch

换句话说,您的指针被声明为指向成员函数类型的指针。这样的指针不能保存静态成员函数的地址。静态成员函数和非静态成员函数是完全不同性质的野兽。相应的指针类型不兼容,不能相互转换。这就是你错误的原因。

这可能是看起来像

ns::ClassA (*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (*ClassA_foo2)(double) = &ns::ClassA::foo;

即。左侧的指针应声明为普通函数指针,而不是成员函数指针。

答案 2 :(得分:0)

ns::ClassA (ns::ClassA::*ClassA_foo1)(long) = &ns::ClassA::foo;
ns::ClassA (ns::ClassA::*ClassA_foo2)(double) = &ns::ClassA::foo;

您似乎正在尝试在文件范围设置静态成员对ClassA_foo1ClassA_foo2。如果是这样,这不是有效的语法。定义静态成员的语法是

SomeType ClassName::member = initializer;

最好使用typedef来声明和定义ClassA_foo1ClassA_foo2

struct ClassA {
   typedef ClassA (*ClassALongGenerator) (long);
   typedef ClassA (*ClassADoubleGenerator) (double);

   static ClassALongGenerator ClassA_foo1;
   static ClassADoubleGenerator ClassA_foo2;
};

然后在某个源文件的文件范围

ns::ClassALongGenerator ClassA_foo1 = ns::ClassA::foo;
ns::ClassADoubleGenerator ClassA_foo2 = ns::ClassA::foo;