关于C++标准over.over#note-2的含义及示例问询
关于C++标准over.over#note-2的示例解释
先贴出标准原文:
若没有目标,则选择所有具名的非模板函数;否则,若非模板函数类型F(经函数指针转换后)与目标类型FT完全相同,则选择该函数。Note 2说明:匹配成员函数指针类型时,会忽略函数所属的类。
核心逻辑
简单说:当你要把成员函数名转换成成员函数指针类型时,编译器只检查函数的**签名(返回值、参数列表、const/volatile限定等)**是否和目标指针类型的签名完全一致——哪怕这个函数属于另一个完全不同的类,也会被视为匹配项。
示例1:跨类成员函数指针赋值
#include <iostream> class Cat { public: void make_sound(int volume) { std::cout << "Cat meows at volume " << volume << "\n"; } }; class Dog { public: void make_sound(int volume) { std::cout << "Dog mimics cat at volume " << volume << "\n"; } void make_sound(double loudness) { std::cout << "Dog mimics cat with loudness " << loudness << "\n"; } }; int main() { // 目标类型:指向Cat类、参数为int、返回void的成员函数指针 void (Cat::*animal_sound)(int) = &Dog::make_sound; Cat my_cat; // 注:此处赋值合法的核心原因是签名匹配,编译器忽略了Cat和Dog是不同类的事实 // 反向赋值同样合法 void (Dog::*dog_sound)(int) = &Cat::make_sound; }
这段代码里,&Dog::make_sound能赋值给void(Cat::*)(int)类型变量,完全是Note2规则的作用——编译器只核对签名,不关注所属类的差异。
示例2:重载函数的匹配选择
class Apple { public: void taste() { std::cout << "Apple tastes sweet\n"; } void taste(int ripeness) { std::cout << "Apple tastes " << ripeness << "/10 sweet\n"; } }; class Orange { public: void taste(int ripeness) { std::cout << "Orange tastes " << ripeness << "/10 tangy\n"; } }; int main() { // 目标类型明确是带int参数的成员函数指针 void (Apple::*tester)(int) = &Orange::taste; // 编译器直接选中Orange::taste(int),因为签名和目标类型完全匹配,完全不在意所属类是Orange而非Apple }
在重载场景下,只要目标类型确定,编译器会跳过类的差异,直接匹配签名一致的函数。
内容的提问来源于stack exchange,提问作者Enlico
相关产品推荐
相关产品推荐

