父类虚函数,子类声明为非虚,会有什么特性

TGame 2013-11-06 10:52:27
class A
{
virtual void Func(int nX);
}

class B : public A
{
void Func(int nX);
}

A* p = new B;
p->Func(5);

我想用A的接口Func,但是可以被子类(C、D...)重载,所以A里Func()声明为虚函数
但是B不会再有子类了,B中重载的Func函数(同名同参数)不声明为虚的,
那p->Func()会调用B的实现吗?
...全文
501 23 打赏 收藏 转发到动态 举报
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
todd_leftcode 2013-11-11
  • 打赏
  • 举报
回复
顶楼上。 很多把override和overload都叫重载的, 或者把 override和overwrite都叫重写的。比如msdn有时把override翻译成重写,而 overwite 翻译成隐藏。还有一些书、文章把overload翻译成过载,而override翻译成重载,overwrite翻译成重写。
Bluuuuuue 2013-11-11
  • 打赏
  • 举报
回复
引用 22 楼 Bluuuuuue 的回复:
大概应该这么写:


class A
{
virtual void Func(int nX);
}

class B : public A
{
void Func(int nX)
{

    //调用父类的函数实现
    A::Func(int nX);
};
}

A* p = new B;
p->Func(5);

实现的地方有点问题:应该是调用 A::Func(nX);
Bluuuuuue 2013-11-11
  • 打赏
  • 举报
回复
大概应该这么写:


class A
{
virtual void Func(int nX);
}

class B : public A
{
void Func(int nX)
{

    //调用父类的函数实现
    A::Func(int nX);
};
}

A* p = new B;
p->Func(5);

rmaly 2013-11-11
  • 打赏
  • 举报
回复
父类是虚函数了,子类写不写都是虚的了
  • 打赏
  • 举报
回复
楼主好好区分一下,这三个单词吧: Overload、Overwrite和Override的概念比较容易混淆,而且Overwrite和Override的中文翻译五花八门,让人很Confuse,顾保持英文原意: Overload 重载: 在C++程序中,可以将语义、功能相似的几个函数用同一个名字表示,但参数不同(包括类型、顺序不同),即函数重载。 (1)相同的范围(在同一个类中); (2)函数名字相同; (3)参数不同; 请注意,重载解析中不考虑返回类型,而且在不同的作用域里声明的函数也不算是重载。 Override: 是指派生类函数覆盖基类函数,特征是: (1)不同的范围(分别位于派生类与基类); (2)函数名字相同; (3)参数相同; (4)基类函数必须有virtual 关键字。 Overwrite: 是指派生类的函数屏蔽了与其同名的基类函数,规则如下: (1)如果派生类的函数与基类的函数同名,但是参数不同。此时,不论有无virtual关键字,基类的函数将被隐藏。 (2)如果派生类的函数与基类的函数同名,并且参数也相同,但是基类函数没有virtual关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。
dyw 2013-11-08
  • 打赏
  • 举报
回复
是啊,父类里virtual了,那就是virtual了。调用的应该是离它最近的那个祖先的版本。
  • 打赏
  • 举报
回复
class a { public: virtual void func() { printf("这个是a的func\n"); } void func2() { printf("这个是a的func2\n"); } }; class b :public a { public: virtual void func() { printf("这个是 b 的func\n"); } void func2() { printf("这个是 b 的func2\n"); } }; int _tmain(int argc, _TCHAR* argv[]) { a * test = new b; test->func(); //这个是重载(多态) 指针实际上是父类的 test->func2();//这个是重写 a* test2 = new a; test2->func(); test2->func2(); b* test3 = new b; test3->func(); test3->func2(); getchar(); return 0; }
menzi11 2013-11-07
  • 打赏
  • 举报
回复
引用 2 楼 taquguodedifang 的回复:
[quote=引用 1 楼 ganpengjin1 的回复:] 那个不是重载,是重写! A* p = new B; p->Func(5); 如果父类在你的func上没有加上virtual那此时调用的父类,否则,子类的方法!
别纠结中文翻译, 父类func是virtual的,子类func声明为非虚的,p->Func()会调用子类方法?[/quote] 重载和重写完全不同,不是翻译问题
如此美丽的你 2013-11-07
  • 打赏
  • 举报
回复

<<深度探索c++对象模型>>你值得拥有。
lm_whales 2013-11-07
  • 打赏
  • 举报
回复
引用 12 楼 QQ575787460 的回复:
自动为虚了都
虚函数会遗传的,直接就虚了。
zmn0079 2013-11-06
  • 打赏
  • 举报
回复
这个问题,这段例子代码,好像前几天就在论坛里看见过?
Adol1111 2013-11-06
  • 打赏
  • 举报
回复
看错问题了,我以为是父类不加virtual。父类加了virtual,子类加不加virtual都无所谓了。同5楼。
Bluuuuuue 2013-11-06
  • 打赏
  • 举报
回复
应该加不加都一样,如果父类不加的话,子类算是重写,然后这个函数就没有动态绑定的功能了,用父类指针调用该函数的时候,就直接调用父类的函数,而不是根据其指向的对象动态选择
你怎么了熊吉 2013-11-06
  • 打赏
  • 举报
回复
1.重载和重写是两个不同的事情 2.父类加了virtual,子类就默认virtual了,加不加都一样
Adol1111 2013-11-06
  • 打赏
  • 举报
回复
如果父类不写virtual的话,就是静态绑定了,调用的是父类的方法。如果是virtual的话,那么是一个动态绑定,会绑定子类的方法。《Effective C++》条款36有详细介绍。
漫步者、 2013-11-06
  • 打赏
  • 举报
回复
引用 2 楼 taquguodedifang 的回复:
[quote=引用 1 楼 ganpengjin1 的回复:] 那个不是重载,是重写! A* p = new B; p->Func(5); 如果父类在你的func上没有加上virtual那此时调用的父类,否则,子类的方法!
别纠结中文翻译, 父类func是virtual的,子类func声明为非虚的,p->Func()会调用子类方法?[/quote] 是的,是否重写,与子类是否声明virtual 无关,只与父类有关!
TGame 2013-11-06
  • 打赏
  • 举报
回复
引用 1 楼 ganpengjin1 的回复:
那个不是重载,是重写! A* p = new B; p->Func(5); 如果父类在你的func上没有加上virtual那此时调用的父类,否则,子类的方法!
别纠结中文翻译, 父类func是virtual的,子类func声明为非虚的,p->Func()会调用子类方法?
漫步者、 2013-11-06
  • 打赏
  • 举报
回复
那个不是重载,是重写! A* p = new B; p->Func(5); 如果父类在你的func上没有加上virtual那此时调用的父类,否则,子类的方法!
jackzooty 2013-11-06
  • 打赏
  • 举报
回复
会调用B中的实现。在基类中定义一个virtual函数,使得该类没有被封装,只是说明其子类(或子类的子类。。。)会实现这样的一个函数。 访问A类时要使用B的实现,需要将指向B类对象的指针转换成指向A类对象的指针(上行转换是安全的)并将其赋予A类对象(事实上上行转换能隐式执行)。
coderchenjingui 2013-11-06
  • 打赏
  • 举报
回复
自动为虚了都
加载更多回复(3)
动态多态编程的好处 首先百度自己去弄懂什么是静态多态?什么是动态多态? 1,能使继承基类的子类重写(覆盖)基类定义的相同函数名字和参数的虚函数接口,使子类对象更符合自己的要求或特征一个简单粗暴的比喻就是假设人是基类,派生出了子类男人和女人.则子类男人和女人拥有基类人的相同特征或行为---如吃饭,要睡觉....但男人类和女人类也有不同的地方---如男的有jj,女的没有.解决这个问题就是在基类人定义一个虚函数接口,具体怎么定义,由继承的子类去自己定义,通过自定义,子类有了符合自己的特征 2,转自网上的一个比喻将父类比喻为电脑的外设接口,子类比喻为外设,现在我有移动硬盘、U盘以及MP3,它们3个都是可以作为存储但是也各不相同。如果我在写驱动的时候,我用个父类表示外设接口,然后在子类中重写父类那个读取设备的虚函数,那这样电脑的外设接口只需要一个。但如果我不是这样做,而是用每个子类表示一个外设接口,那么我的电脑就必须有3个接口分别来读取移动硬盘、U盘以及MP3。若以后我还有SD卡读卡器,那我岂不是要将电脑拆了,焊个SD卡读卡器的接口上去?所以,用父类的指针指向子类,是为了面向接口编程。大家都遵循这个接口,弄成一样的,到哪里都可以用。 3,提高程序的可复用性,提高可扩充行和可维护性,一个接口,多种实现,各自不同. 动态多态的基础知识:首先百度自己去弄懂什么是静态多态?什么是动态多态? 易语言的类方法全部是强制成虚函数的具体参考易语言目录下的例子e\samples\基本例程\面向对象编程.e易语言面对对象编程类的创建与使用help.plgzs.com/zlsc/oop.htm 但易语言对类的封装并不完美,与标准的c++的类很多功能没有 易语言是c++写的,所以要在在这之前必须要弄懂c++中什么是重写,重载,隐藏,3个不同的概念 ,不懂就百度,另外别拿C#和java的对比c++的重写 1.重写必须继承,重载不用。2.重写的方法名,参数数目相同,参数类型兼容,重载的方法名相同,参数列表不同。3.重写的方法修饰符大于等于父类的方法,重载和修饰符无关。4.重写不可以抛出父类没有抛出的一般异常,可以抛出运行时异常   特点:   1. 指不同作用域中(派生类和基类)同名函数的定义   2. 函数名、参数均完全相同   3. 基类对应方法前有 virtual,即被声明虚函数   作用:   基类指针和引用在调用对应方法时,根据所指对象类型实现动态绑定。
多态的好处 1,能使继承基类的子类重写(覆盖)基类定义的相同函数名字和参数的虚函数接口,使子类对象更符合自己的要求或特征 一个简单粗暴的比喻就是 假设人是基类,派生出了子类男人和女人. 则子类男人和女人拥有基类人的相同特征或行为---如吃饭,要睡觉.... 但男人类和女人类也有不同的地方---如男的有jj,女的没有. 解决这个问题就是在基类人定义一个虚函数接口,具体怎么定义,由继承的子类去自己定义,通过自定义,子类有了符合自己的特征 2,转自网上的一个比喻 将父类比喻为电脑的外设接口,子类比喻为外设,现在我有移动硬盘、U盘以及MP3,它们3个都是可以作为存储但是也各不相同。如果我在写驱动的时候,我用个父类表示外设接口,然后在子类中重写父类那个读取设备的虚函数,那这样电脑的外设接口只需要一个。但如果我不是这样做,而是用每个子类表示一个外设接口,那么我的电脑就必须有3个接口分别来读取移动硬盘、U盘以及MP3。若以后我还有SD卡读卡器,那我岂不是要将电脑拆了,焊个SD卡读卡器的接口上去? 所以,用父类的指针指向子类,是为了面向接口编程。大家都遵循这个接口,弄成一样的,到哪里都可以用。 3,提高程序的可复用性,提高可扩充行和可维护性,一个接口,多种实现,各自不同. 动态多态的基础知识: 首先百度自己去弄懂什么是静态多态?什么是动态多态 易语言的类方法全部是强制成虚函数的 具体参考易语言目录下的例子 e\samples\基本例程\面向对象编程.e 易语言面对对象编程  类的创建与使用 help.plgzs.com/zlsc/oop.htm 但易语言对类的封装并不完美,与标准的c++的类很多功能没有 易语言是c++写的,所以要在在这之前必须要弄懂c++中什么是重写,重载,隐藏,3个不同的概念,不懂就百度,另外别拿C#和java的对比c++的重写 1.重写必须继承,重载不用。 2.重写的方法名,参数数目相同,参数类型兼容,重载的方法名相同,参数列表不同。 3.重写的方法修饰符大于等于父类的方法,重载和修饰符无关。 4.重写不可以抛出父类没有抛出的一般异常,可以抛出运行时异常 特点: 1. 指不同作用域中(派生类和基类)同名函数的定义 2. 函数名、参数均完全相同 3. 基类对应方法前有 virtual,即被声明虚函数 作用: 基类指针和引用在调用对应方法时,根据所指对象类型实现动态绑定。

64,651

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧