You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 21:58:21