C++重载与重写的各种问题

本文详细探讨了C++中的函数重载与重写概念,包括const关键字的作用、默认参数的影响及访问修饰符的影响,并通过实例展示了如何区分重载与重写。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

C++重载与重写的各种问题

知识复习

在探究C++虚函数造成的各种重写的问题之前,我们先复习一下C++中的函数重载

1.const在函数重载中的定义

对于下几种情况,哪几个算是函数重载呢?

//情况1
void fun(int a);
void fun(const int a);

//情况2
void fun(int* a);
void fun(const* a);

//情况3
void fun(int* a)
void fun(int const * a);

//情况4
void fun(int *a)
void fun(int *const a);

答案是:2,3是函数重载,1,4是重定义

情况1

我们可以假设这样的调用情况

fun(1)

那么对于第一种定义,我们可以看到

int a=1

是可以的,而第二种定义

const int a=1

同样也没问题,所以这里我们也就可以理解这里为什么是重定义了

情况2

我们可以假设这样的调用情况

const int b=1;fun(&b);

那么对于第一种定义,我们可以看到

int* a=&b

是不可以的,因为const int*是不可以向int *装换的,而第二种定义

const int* a=&b

毫无问题,所以我们可以通过这种方法将两种方法区分出来,那么传入int*调用的是那种呢?是第一种,因为,第一种显然更匹配一些。

情况3

哈哈,const int *int const *是等价的,所以如同情况2一样

情况4

这种情况就和情况1类似,这里就不多做解释了

总结

在C++中,函数重载还是重定义靠的是,是否有一种调用情况能将两种函数区分开来,如果能就是重载,否则就是重定义。

const在重载与重写中的作用

我们考虑这样的情况,以下两个函数哪个是重载,哪个是重写?

class A
{
    public:
        void test_const(int a)
        {
        }
        void test_const_function(int a)
        {
        }
};

class B:public A
{
    public:
        //情况1
        void test_const(int a)
        {
        }
        //情况2
        void test_const_function(int a) const
        {
        }

}

答案是情况1是重写,情况2是重载

情况1

这个很简单,相当于上边的情况1,因为我们无法区分调用在传入相同参数调用哪个函数,所以是重定义,但是用在虚函数上边就变成了重写。

情况2

但这是为什么呢?

其实是因为在类里边

void test_const_function(int a)
{
}
        |
        |
        |会被改写成
        |
        v
void test_const_function(A&a,int a)
{
}


void test_const_function(int a) const
{
}
        |
        |
        |会被改写成
        |
        v
void test_const_function(const A&a,int a)
{
}

那么就变成了上边情况2,所以变成了重载,重写失败。

默认参数在重载与重写中的作用

情况如下,那些会调用成功呢?

class A
{
    void test_default_parament(int a,int b=4)
    {
        cout<<"A:"<<a<<" B:"<<b<<endl;
    }
}
class B:public A
{
    void test_default_parament(int a=0,int b=0)
    {
        cout<<"A:"<<a<<" B:"<<b<<endl;
    }
}
int main()
{
    B* bpoint=new B
    A* apoint=bpointer;
    //情况1
    apoint-> test_default_parament(1,2);
    //情况2
    apoint-> test_default_parament(1);
    //情况3
    apoint-> test_default_parament();

}

答案是情况1和情况2,情况3会被认为缺少参数

分析

根本原因是默认参数时静态绑定的

apoint-> test_default_parament(1);
        |
        |
        |
        V
apoint-> test_default_parament(1,4)
//绑定父类的默认参数

apoint-> test_default_parament(1);
        |
        |
        |
        V
apoint-> test_default_parament(1,0)
//绑定子类函数的默认参数

说以略微思考一下,就可以知道为什么上边会调用失败了吧,更深一步,我们也可以知道函数具体输出的结果

总结

最好的方法是,不要在虚函数中使用默认参数,如果我们真的想用怎么办呢,世界之大,方法总会有的么。

private,public在重载与重写中的作用

有以下几种情况,哪几种会调用成功呢?

class A
{
    public:
        virtual void Test_public()
        {
            cout<<"father"<<endl;
        }
    private:
        virtual void Test_private()
        {
            cout<<"father"<<endl;
        }

};
class B:public A
{
    public:
        virtual const int Test_private()
        {
       }
    private:
        virtual void Test_public()
       {
       }
};
int main()
{
    B* bpointer=new B;
    A* apointer=bpointer;
    bpointer->Test_private();
    bpointer->Test_public();
    apointer->Test_public();
    apointer->Test_private();


    return 0;
}

嘿嘿,这里不给出答案了,比较难打,但是代码写的比较全,各位可以运行一下

为什么呢?其实本质这里也是一样的,对于操作权限都是静态绑定的

总结

  • 函数权限,默认参数都是静态绑定的
  • 函数重载和重定义都是依靠是否能有一种调用情况区分调用函数的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值