c++ - 层次结构中的成员函数指针

标签 c++ casting pointer-to-member

我正在使用定义接口(interface)的库:

template<class desttype>
void connect(desttype* pclass, void (desttype::*pmemfun)());

我有一个小层次结构

class base {
   void foo();
};

class derived: public base { ... };

derived的一个成员函数中,我想调用

connect(this, &derived::foo);

但是看起来&derived::foo其实是base的一个成员函数指针; gcc 吐出

error: no matching function for call to ‘connect(derived* const&, void (base::* const&)())’

我可以通过显式地将 this 转换为 base * 来解决这个问题;但为什么编译器不能将调用与 desttype = base 匹配(因为 derived * 可以隐式转换为 base *)?

另外,为什么&derived::foo不是derived的成员函数指针?

最佳答案

首先,当你执行 &class::member 时,结果的类型总是基于成员实际声明的类。这就是一元 & 的工作方式C++。

其次,代码无法编译,因为模板参数推导失败。它从第一个参数导出 desttype = derived,而从第二个参数导出 desttype = base。这就是编译失败的原因。 C++ 中的模板参数推导规则没有考虑this 可以转换为base * 类型这一事实。此外,可以争辩说,不是将 this 转换为 base * 类型,正确的方法是将 &derived::foo 从指针转换为 - to-base-member 指向派生成员类型的指针。这两种方法同样可行(见下文)。

第三,C++ 中的成员指针遵循反变 规则,这意味着指向基类成员的指针可以隐式转换为指向派生类成员的指针。在您的情况下,您需要做的就是通过显式指定参数来帮助编译器完成模板参数推导,并且代码应该编译

 connect<derived>(this, &derived::foo);

由于 &derived::foo 指针的反方差,上面应该编译,即使它是指向 base 成员的指针。或者你可以做

 connect<base>(this, &derived::foo);

由于 this 指针的协方差,这也应该编译。

您还可以对实际参数使用显式转换(正如您在问题中提到的那样)来解决演绎歧义,但我认为在这种情况下,显式指定的模板参数看起来更好。

关于c++ - 层次结构中的成员函数指针,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2602254/

相关文章:

c++ - 没有新成员的模板化多态派生类的大小

c++ - C++11 std::string::operator[] 会返回空终止缓冲区吗

c++ - 检查是否在 DWORD 中设置了某些位

c++ - 覆盖具有不同返回类型的遗留 C 函数的模板函数

c++ - 如何将类成员函数传递给第 3 方库中的方法?

Java 将 int 转换为 char 不起作用

java - 安卓 : Cannot cast from View to Button

c - 严格别名和强制转换 union 指针

c++ - 指向类方法错误的指针数组 C++11

c++ - 指向虚拟成员函数的指针。它是如何工作的?