为啥当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数?

Posted

技术标签:

【中文标题】为啥当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数?【英文标题】:why compiler is not showing error when I have two functions one will take base class and one will take derived class as parameters?为什么当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数? 【发布时间】:2017-10-18 02:12:18 【问题描述】:

我有一个基类和一个派生自基类的派生类。每个人都有一个好友函数,它重载operator+,如下所示。

#include <iostream>

using namespace std;

class base

    private:
        int x;

    public:
        base(int a) : x(a)
        
        

        void printx()
        
            cout << "x : " << x << endl;
        

        friend void operator+(int data, base &obj);
;

void operator+(int data, base &obj)

    obj.x = data + obj.x;


class derived : public base

    private:
        int y;

    public:
        derived(int a, int b) : base(a), y(b)
        
        

        void printy()
        
            cout << "y : " << y << endl;
        

        friend void operator+(int data, derived &obj);
;

void operator+(int data, derived &obj)

    operator+(data, obj);
    obj.y = data + obj.y;


int main()

    derived c(2, 3);

    4 + c;

    c.printx();
    c.printy();

我认为编译器会因为友元函数而抛出错误。

void operator+(int data, base &obj)
void operator+(int data, derived &obj)

将基类对象作为参数的函数也可以将派生类对象作为基类是派生类的一部分。所以我认为编译器会显示一个错误,因为这两个函数都可以将派生类对象作为参数。但是这个程序运行良好。谁能解释一下为什么编译器没有显示错误?

【问题讨论】:

反对者。请让我知道这个问题有什么问题。 可能是因为问题太简单,只值得花几分钟搜索一下? 抛出异常。显示错误。不要滥用标准术语。 【参考方案1】:

简单回答:这两个函数不冲突,因为它们没有相同的签名。

当您使用基实例调用一个时,它不适合派生类引用,因此将调用 operator+(int, base&amp;)

当您使用派生实例调用一个时,基函数需要隐式转换,而派生函数不需要,因此将调用 operator+(int, derived&amp;)

参考:函数Overload Resolution,参见可行函数最佳可行函数部分。

1) F1 的至少一个参数的隐式转换优于 F2 的该参数的相应隐式转换

当然没有隐式转换比一个隐式转换“更好”,那么operator+(int, base&amp;)就不会被一个devired对象调用。

【讨论】:

【参考方案2】:

对于4 + c;,overload resolution会尽量选出最好的; operator+(int data, derived &amp;obj) 是完全匹配,operator+(int data, base &amp;obj) 需要隐式转换(从derivedbase),然后选择operator+(int data, derived &amp;obj),这里没有歧义错误。

【讨论】:

以上是关于为啥当我有两个函数时编译器没有显示错误,一个将基类作为参数,一个将派生类作为参数?的主要内容,如果未能解决你的问题,请参考以下文章

将基类向量传递给接受超类向量的函数

将基类作为参数传递给虚函数时避免使用 dynamic_cast

为啥我不能使用子类的指针访问基类的公共函数?

为啥以及何时使用多态性将基类指向 C++ 中的派生类 [重复]

如何将基类的未知子类放在一个数据结构中并在 C++ 中调用重写的基类函数

systemverilog 为啥要用$cast类型转换函数