您的位置:首页 > 编程语言 > C语言/C++

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

2016-09-12 11:10 288 查看

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;
}


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

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

总结

函数权限,默认参数都是静态绑定的

函数重载和重定义都是依靠是否能有一种调用情况区分调用函数的
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: