返回信息流覆盖的方法的返回值必须和被覆盖的方法的返回一致;参数、返回值只要有一个不同则不再是覆盖,而是隐藏?
这是一条镜像帖。来源:北邮人论坛 / cpp / #74838同步于 2013/10/27
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖
关于override覆盖问题
Mulany
2013/10/27镜像同步11 回复
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
1 重载与覆盖
成员函数被重载的特征:
(1)相同的范围(在同一个类中) ;
(2)函数名字相同;
(3)参数不同;
(4)virtual 关键字可有可无。
(5)名称和形参表相同,只有返回值不同,不管有无virtual,无法通过编译
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类) ;
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有 virtual 关键字。
(5)名称和形参表相同,只有返回值不同,基类函数有virtual,无法通过编译;基类函数没有virtual,不属于覆盖,而是隐藏。
加入隐藏的概念后:
(1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载混淆) 。
(2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有 virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)
(3)如果派生类的函数与基类的函数同名,并且参数也相同,但是返回值不同,如果基类函数没有virtual关键字,此时,基类的函数被隐藏(和重载时候的错误声明有作用域的区别)
(4)如果派生类的函数与基类的函数同名,并且参数也相同,但是返回值不同,如果基类函数有virtual关键字,无法通过编译
部分引自:http://dlut2007.blog.sohu.com/71147756.html
这几个概念很容易混淆,网上讨论的也很充分,理解它们最好的办法就是自己写一些代码验证一下,然后看看经典教材上大师们是如何解释为什么是这样的,
C++ primer上面对于一般函数的重载花了很多笔墨,也探讨了函数重载和重复声明以及只有返回值不同的错误声明的区别,还有一些形式上看上去像重载实际是重复声明的例子。
More Effective C++里面对于派生类隐藏基类方法专门用条款33来介绍并建议非必要不要这么做的原因。
具体到你的问题,答案是肯定的,如果你的代码可以编译的话,也就是说基类同名同参函数没有virtual关键字的话,是属于隐藏;如果同名同返回值类型,只是形参表不同,不管有没有virtual,就是隐藏。
好详细,我百度过多次,始终感觉比较混乱
【 在 rollse 的大作中提到: 】
: 1 重载与覆盖
: 成员函数被重载的特征:
: (1)相同的范围(在同一个类中) ;
: ...................
关于覆盖的(4)基类函数必须有 virtual 关键字。没有的话就不是覆盖吗?这和通常的概念有些相悖额
【 在 rollse 的大作中提到: 】
: 1 重载与覆盖
: 成员函数被重载的特征:
: (1)相同的范围(在同一个类中) ;
: ...................
覆盖的英文是override,指的就是实现多态的时候派生类成员函数在类的虚表中对基类虚函数的覆盖,你理解的覆盖是什么意思?
【 在 Mulany 的大作中提到: 】
: 关于覆盖的(4)基类函数必须有 virtual 关键字。没有的话就不是覆盖吗?这和通常的概念有些相悖额
我最初理解的覆盖是指调用基类和子类都有的同名函数时,只会调用到子类的,不会调用到基类的
【 在 rollse 的大作中提到: 】
: 覆盖的英文是override,指的就是实现多态的时候派生类成员函数在类的虚表中对基类虚函数的覆盖,你理解的覆盖是什么意思?
首先要明确概念:多态是基于虚函数的覆盖机制的,用类的虚函数表来实现,当你用指向基类类型的引用或指针来调用虚函数的时候,实际被调用的函数由该引用或者指针指向的实际类型决定;也就是说Base *d = new Derived();里面的d调用的虚函数如果在Derived里面被覆盖,就是这个用来覆盖的Derived定义个虚函数(如果基类有一个虚函数,其派生类中用来覆盖它的函数不论是否有无virtual关键在,都被认为是虚函数).
如果Base *b = new Base(), 那就调用到基类的虚函数了,前提是该基类没有纯虚函数,否则该类就是抽象类了,不能直接产生实例。
请参考c++ primer评注版作者的博文http://blog.csdn.net/haoel/article/details/1948051/
【 在 Mulany 的大作中提到: 】
: 我最初理解的覆盖是指调用基类和子类都有的同名函数时,只会调用到子类的,不会调用到基类的
不好意思,我没表达清楚。
假设基类由函数void fun(){};子类没有,那么通过子类对象derivedobj.fun();则调用的是基类的函数。假设子类中也有void fun(){。。。};此时derivedobj.fun();就会调用子类的。按我以前理解,虽然此处没有virtual,但也属于覆盖。不知道您的概念里算不算呢
【 在 rollse 的大作中提到: 】
: 首先要明确概念:多态是基于虚函数的覆盖机制的,用类的虚函数表来实现,当你用指向基类类型的引用或指针来调用虚函数的时候,实际被调用的函数由该引用或者指针指向的实际类型决定;也就是说Base *d = new Derived();里面的d调用的虚函数如果在Derived里面被覆盖,就是这个用来覆盖的Derived定义个虚函数(如果基类有一个虚函数,其派生类中用来覆盖它的函数不论是否有无virtual关键在,都被认为是虚函数).
: 如果Base *b = new Base(), 那就调用到基类的虚函数了,前提是该基类没有纯虚函数,否则该类就是抽象类了,不能直接产生实例。
: 请参考c++ primer评注版作者的博文http://blog.csdn.net/haoel/article/details/1948051/
你的描述不成立:
#include<iostream>
#include<string>
using namespace std;
void PrintOutput(const string output)
{
cout<<output<<endl;
}
class A
{
public:
A(){PrintOutput("An A instance is initializing...");}
void func(){PrintOutput("A::func()");}
~A(){PrintOutput("An A instance is being destroyed...");}
};
class B:public A
{
public:
B()
{
piVar = (int *)malloc(sizeof(int) * 100);
PrintOutput("An B instance is initializing...");
}
void func(){PrintOutput("B::func()");}
~B()
{
free(piVar);
PrintOutput("An B instance is being destroyed...");
}
private:
int * piVar;
};
int main()
{
A *b = new B();
b->func();
//do what you want
delete b;
return 0;
}
输出为:
An A instance is initializing...
An B instance is initializing...
A::func()
An A instance is being destroyed...
可以看到b.func()调用的还是基类的方法。
#include<iostream>
#include<string>
using namespace std;
void PrintOutput(const string output)
{
cout<<output<<endl;
}
class A
{
public:
A(){PrintOutput("An A instance is initializing...");}
void func(){PrintOutput("A::func()");}
~A(){PrintOutput("An A instance is being destroyed...");}
};
class B:public A
{
public:
B()
{
piVar = (int *)malloc(sizeof(int) * 100);
PrintOutput("An B instance is initializing...");
}
void func(){PrintOutput("B::func()");}
~B()
{
free(piVar);
PrintOutput("An B instance is being destroyed...");
}
private:
int * piVar;
};
int main()
{
B *b = new B(); //此处改为B类对象指针
b->func(); //这地方并不会调用到A的func(),我就是想确定一下这种情况算是覆盖吗?
//do what you want
delete b;
return 0;
}