我有一个库,其类定义为:
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;
我认为它们可能是静态的,但在返回类型之前或之后放置静态会产生相同的错误。
答案 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_foo1
和ClassA_foo2
。如果是这样,这不是有效的语法。定义静态成员的语法是
SomeType ClassName::member = initializer;
最好使用typedef来声明和定义ClassA_foo1
和ClassA_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;