C++ 成员函数重载与 &(和号)

Posted

技术标签:

【中文标题】C++ 成员函数重载与 &(和号)【英文标题】:C++ member function overloading with & (ampersand) 【发布时间】:2016-06-29 07:53:47 【问题描述】:

如何选择正确的error()成员函数?我需要以某种方式投射吗?

using namespace std;

struct test

   int error();
   void error(int x);
   int fun();
;

int main() 
   auto f1 = &test::error; // how to pick the correct function?
   auto f2 = &test::fun; // works

【问题讨论】:

【参考方案1】:

你可以明确指定成员函数指针类型。

int (test::*f1)() = &test::error;
void (test::*f2)(int) = &test::error;

【讨论】:

这个;强制转换不是特别必要的,重要的是编译器能够区分应该使用哪个重载(因此需要哪种类型)。 我要补充一点,添加 typedef 会使事情更具可读性:using error_func = int (test::*)(); error_func f1 = &test::error;.【参考方案2】:

我需要以某种方式投射吗?

是的,您可以使用static_cast

static_cast 也可用于消除函数重载的歧义 执行到特定类型的函数到指针转换,如

std::for_each(files.begin(), files.end(),
              static_cast<std::ostream&(*)(std::ostream&)>(std::flush));

所以你可以:

auto f1 = static_cast<int(test::*)()>(&test::error);
auto f2 = static_cast<void(test::*)(int)>(&test::error);

【讨论】:

亲爱的主,这太丑了。 每次看到 C++ 类型语法时,我都会有一种用 Haskell 写东西的冲动。【参考方案3】:

您需要使用static_cast 来消除歧义。

&amp;test::error 不可评估,因为函数已重载。您将其分配给标记为auto 的内容并不立即相关。

一种解决方法是酌情使用static_cast&lt;int(test::*)()&gt;(&amp;test::error)static_cast&lt;void(test::*)(int)&gt;(&amp;test::error)

然后auto 将起作用,因为类型推导不会有歧义。

【讨论】:

【参考方案4】:

既然已经给出了答案,我将提出一个更容易理解的解决方案。如果您不想每次都写出演员表,这种情况非常适合宏:

template<class T>
using test_type_t = T test::*;
#define TEST_CAST(T, F) static_cast<test_type_t<T>>(&F)

auto f1 = TEST_CAST(void(int), test::error);

【讨论】:

【参考方案5】:

当您没有互联网阅读丑陋的函数指针到成员语法时,这是解决方案:

auto err1 = [](test& t)  return t.error(); ;
auto err2 = [](test& t, int x)  return t.error(x); ;

请注意,到目前为止,您将闭包作为类型而不是函数指针。如果您想要函数指针,如果您想在数组中存储具有相同签名的不同成员函数,这很有用,您可以通过+ 将闭包转换为(普通)函数指针(参见here)。

就我目前所见,从概念上讲,您可以用函数到成员指针做任何事情——当然除了调用一个完全需要这样一个指针的例程。而且更好看。

【讨论】:

以上是关于C++ 成员函数重载与 &(和号)的主要内容,如果未能解决你的问题,请参考以下文章

❥关于C++之成员与友元函数重载运算符

C++运算符重载中 重载为类的成员函数和重载为类的友元函数 的区别是啥?

在c++中的继承,如何在子类中重载成员函数

C++入门C++ 函数模板&类模板

C++类与对象(中)

C++ Visual Studio 非标准语法使用 '&' 创建指向成员的指针