【C++】在显示调用基类函数非virtual函数中使用typeid(this)

C++纯虚函数 virtual =0
<a data-traceid="question_detail_above_text_l&&
C++纯虚函数 virtual =0
参考:&(百度空间)
=========================================================================&
C++中的纯虚函数
在C++中的一种函数申明被称之为:纯虚函数(pure virtual function).它的申明格式如下:
class CShape
&&& virtual void Show()
注意红色部分,在普通的虚函数后面加上&
=0&这样就声明了一个pure virtual function.
&& 在什么情况下使用纯虚函数(pure vitrual function)?
1,当想在基类中抽象出一个方法,且该基类只做能被继承,而不能被实例化;
2,这个方法必须在派生类(derived class)中被实现;
&& 如果满足以上两点,可以考虑将该方法申明为pure virtual function.
我们来举个例子,我们先定义一个形状的类(Cshape),但凡是形状我们都要求其能显示自己。所以我们定义了一个类如下:
class CShape
&&& virtual void Show()
但没有CShape这种形状,因此我们不想让CShape这个类被实例化,我们首先想到的是将Show函数的定义(实现)部分删除如下:
class CShape
&&& virtual void Show();
当我们使用下面的语句实例化一个CShape时:
CS& //这是我们不允许的,但仅用上面的代码是可以通过编译(但link时失败)。
&& 怎么样避免一个CShape被实例化,且在编译时就被发现?
答案是:使用pure virtual funcion.
我们再次修改CShape类如下:
class CShape
&&& virtual void Show()
这时在实例化CShape时就会有以下报错信息:
error C2259: 'CShape' : cannot instantiate abstract class due to following members:
warning C4259: 'void __thiscall CShape::Show(void)' : pure virtual function was not defined
&& 我们再来看看被继承的情况,我们需要一个CPoint2D的类,它继承自CShape.他必须实现基类(CShape)中的Show()方法。
&& 其实使用最初的本意是让每一个派生自CShape的类,都要实现Show()方法,但时常我们可能在一个派生类中忘记了实现Show(),为了避免这种情况,pure virtual funcion发挥作用了。
&&&我们看以下代码:
class CPoint2D:public CShape
&CPoint2D()
&&printf(&CPoint2D ctor is invoked/n&);
&void Msg()
&&printf(&CPoint2D.Msg() is invoked/n&);
&/*---I'm sorry to forget implement the Show()---
&void Show()
&&printf(&Show() from CPoint2D/n&);
------------------------------------------------*/
当我们实例化CPoint2D时,在编译时(at the compiling)也会出现如下的报错:
error C2259: 'CShape' : cannot instantiate abstract class due to following members:
warning C4259: 'void __thiscall CShape::Show(void)' : pure virtual function was not defined
&& 如上,我们预防了在派生类中忘记实现基类方法。
也许compiler会说:
哼!如果不在派生类的中实现在Show方法,我编译都不会让你通过。
//--------------------------------------------------------
//now,show the completed code,
//Platform:Winxp+VC6.0
//--------------
#include &iostream&
#include &stdio.h&
class CShape
&virtual void Show()=0;
class CPoint2D:public CShape
&void Msg()
&&printf(&CPoint2D.Msg() is invoked/n&);
/*---I'm sorry to forget implementation of&the Show()--- */
&void Show()
&&printf(&Show() from CPoint2D/n&);
/*------------------------------------------------------*/
void main()
&CPoint2D p2d;&& //如果派生类(CPoint2D)没有实现Show(),则编译不通过
&p2d.Msg();
&CShape *pShape = &p2d;
&pShape-&Show();
&//不能实例化基类
=========================================================================&
C++中的虚函数(virtual function)
1.简介&&&&&虚函数是C++中用于实现多态(polymorphism)的机制。核心理念就是通过基类访问派生类定义的函数。假设我们有下面的类层次:class A{public:&&&&virtual void foo() { cout && &A::foo() is called& &&}};class B: public A{public:&&&&virtual void foo() { cout && &B::foo() is called& &&}};那么,在使用的时候,我们可以:A * a = new B();a-&foo();&&&&&&&// 在这里,a虽然是指向A的指针,但是被调用的函数(foo)却是B的!&&&&这个例子是虚函数的一个典型应用,通过这个例子,也许你就对虚函数有了一些概念。它虚就虚在所谓“推迟联编”或者“动态联编”上,一个类函数的调用并不是在编译时刻被确定的,而是在运行时刻被确定的。由于编写代码的时候并不能确定被调用的是基类的函数还是哪个派生类的函数,所以被成为“虚”函数。&&&&虚函数只能借助于指针或者引用来达到多态的效果,如果是下面这样的代码,则虽然是虚函数,但它不是多态的:class A{public:&&&&virtual void foo();};class B: public A{&&&&virtual void foo();};void bar(){&&&&A&&&&a.foo();&&&// A::foo()被调用}1.1 多态&&&&&在了解了虚函数的意思之后,再考虑什么是多态就很容易了。仍然针对上面的类层次,但是使用的方法变的复杂了一些:void bar(A * a){&&&&a-&foo();&&// 被调用的是A::foo() 还是B::foo()?}因为foo()是个虚函数,所以在bar这个函数中,只根据这段代码,无从确定这里被调用的是A::foo()还是B::foo(),但是可以肯定的说:如果a指向的是A类的实例,则A::foo()被调用,如果a指向的是B类的实例,则B::foo()被调用。这种同一代码可以产生不同效果的特点,被称为“多态”。1.2 多态有什么用?&&&&&多态这么神奇,但是能用来做什么呢?这个命题我难以用一两句话概括,一般的C++教程(或者其它面向对象语言的教程)都用一个画图的例子来展示多态的用途,我就不再重复这个例子了,如果你不知道这个例子,随便找本书应该都有介绍。我试图从一个抽象的角度描述一下,回头再结合那个画图的例子,也许你就更容易理解。&&&&在面向对象的编程中,首先会针对数据进行抽象(确定基类)和继承(确定派生类),构成类层次。这个类层次的使用者在使用它们的时候,如果仍然在需要基类的时候写针对基类的代码,在需要派生类的时候写针对派生类的代码,就等于类层次完全暴露在使用者面前。如果这个类层次有任何的改变(增加了新类),都需要使用者“知道”(针对新类写代码)。这样就增加了类层次与其使用者之间的耦合,有人把这种情况列为程序中的“bad smell”之一。&&&&多态可以使程序员脱离这种窘境。再回头看看1.1中的例子,bar()作为A-B这个类层次的使用者,它并不知道这个类层次中有多少个类,每个类都叫什么,但是一样可以很好的工作,当有一个C类从A类派生出来后,bar()也不需要“知道”(修改)。这完全归功于多态--编译器针对虚函数产生了可以在运行时刻确定被调用函数的代码。1.3 如何“动态联编”&&&&&编译器是如何针对虚函数产生可以再运行时刻确定被调用函数的代码呢?也就是说,虚函数实际上是如何被编译器处理的呢?Lippman在深度探索C++对象模型[1]中的不同章节讲到了几种方式,这里把“标准的”方式简单介绍一下。&&&&我所说的“标准”方式,也就是所谓的“VTABLE”机制。编译器发现一个类中有被声明为virtual的函数,就会为其搞一个虚函数表,也就是VTABLE。VTABLE实际上是一个函数指针的数组,每个虚函数占用这个数组的一个slot。一个类只有一个VTABLE,不管它有多少个实例。派生类有自己的VTABLE,但是派生类的VTABLE与基类的VTABLE有相同的函数排列顺序,同名的虚函数被放在两个数组的相同位置上。在创建类实例的时候,编译器还会在每个实例的内存布局中增加一个vptr字段,该字段指向本类的VTABLE。通过这些手段,编译器在看到一个虚函数调用的时候,就会将这个调用改写,针对1.1中的例子:void bar(A * a){&&&&a-&foo();}会被改写为:void bar(A * a){&&&&(a-&vptr[1])();}&&&&因为派生类和基类的foo()函数具有相同的VTABLE索引,而他们的vptr又指向不同的VTABLE,因此通过这样的方法可以在运行时刻决定调用哪个foo()函数。&&&&虽然实际情况远非这么简单,但是基本原理大致如此。1.4 overload和override&&&&&虚函数总是在派生类中被改写,这种改写被称为“override”。我经常混淆“overload”和“override”这两个单词。但是随着各类C++的书越来越多,后来的程序员也许不会再犯我犯过的错误了。但是我打算澄清一下:override是指派生类重写基类的虚函数,就象我们前面B类中重写了A类中的foo()函数。重写的函数必须有一致的参数表和返回值(C++标准允许返回值不同的情况,这个我会在“语法”部分简单介绍,但是很少编译器支持这个feature)。这个单词好象一直没有什么合适的中文词汇来对应,有人译为“覆盖”,还贴切一些。&overload约定成俗的被翻译为“重载”。是指编写一个与已有函数同名但是参数表不同的函数。例如一个函数即可以接受整型数作为参数,也可以接受浮点数作为参数。&2. 虚函数的语法&&&&&虚函数的标志是“virtual”关键字。2.1 使用virtual关键字&&&&&考虑下面的类层次:class A{public:&&&&virtual void foo();};class B: public A{public:&&&&void foo();&&&&// 没有virtual关键字!};class C: public B&&// 从B继承,不是从A继承!{public:&&&&void foo();&&&&// 也没有virtual关键字!};&&&&这种情况下,B::foo()是虚函数,C::foo()也同样是虚函数。因此,可以说,基类声明的虚函数,在派生类中也是虚函数,即使不再使用virtual关键字。2.2 纯虚函数&&&&&如下声明表示一个函数为纯虚函数:class A{public:&&&&virtual void foo()=0;&&&// =0标志一个虚函数为纯虚函数};&&&&一个函数声明为纯虚后,纯虚函数的意思是:我是一个抽象类!不要把我实例化!纯虚函数用来规范派生类的行为,实际上就是所谓的“接口”。它告诉使用者,我的派生类都会有这个函数。2.3 虚析构函数&&&&&析构函数也可以是虚的,甚至是纯虚的。例如:class A{public:&&&&virtual ~A()=0;&&&// 纯虚析构函数};&&&&当一个类打算被用作其它类的基类时,它的析构函数必须是虚的。考虑下面的例子:class A{public:&&&&A() { ptra_ = new char[10];}&&&&~A() { delete[] ptra_;}&&&&&&&&// 非虚析构函数private:&&&&char * ptra_;};class B: public A{public:&&&&B() { ptrb_ = new char[20];}&&&&~B() { delete[] ptrb_;}private:&&&&char * ptrb_;};void foo(){&&&&A * a = new B;&&&&}&&&&在这个例子中,程序也许不会象你想象的那样运行,在执行delete a的时候,实际上只有A::~A()被调用了,而B类的析构函数并没有被调用!这是否有点儿可怕?&&&&如果将上面A::~A()改为virtual,就可以保证B::~B()也在delete a的时候被调用了。因此基类的析构函数都必须是virtual的。&&&&纯虚的析构函数并没有什么作用,是虚的就够了。通常只有在希望将一个类变成抽象类(不能实例化的类),而这个类又没有合适的函数可以被纯虚化的时候,可以使用纯虚的析构函数来达到目的。2.4 虚构造函数?&&&&&构造函数不能是虚的。3. 虚函数使用技巧 3.1 private的虚函数&&&&&考虑下面的例子:class A{public:&&&&void foo() { bar();}private:&&&&virtual void bar() { ...}};class B: public A{private:&&&&virtual void bar() { ...}};&&&&在这个例子中,虽然bar()在A类中是private的,但是仍然可以出现在派生类中,并仍然可以与public或者protected的虚函数一样产生多态的效果。并不会因为它是private的,就发生A::foo()不能访问B::bar()的情况,也不会发生B::bar()对A::bar()的override不起作用的情况。&&&&这种写法的语意是:A告诉B,你最好override我的bar()函数,但是你不要管它如何使用,也不要自己调用这个函数。3.2 构造函数和析构函数中的虚函数调用&&&&&一个类的虚函数在它自己的构造函数和析构函数中被调用的时候,它们就变成普通函数了,不“虚”了。也就是说不能在构造函数和析构函数中让自己“多态”。例如:class A{public:&&&&A() { foo();}&&&&&&&&// 在这里,无论如何都是A::foo()被调用!&&&&~A() { foo();}&&&&&&&// 同上&&&&virtual void foo();};class B: public A{public:&&&&virtual void foo();};void bar(){&&&&A * a = new B;&&&&}&&&&如果你希望delete a的时候,会导致B::foo()被调用,那么你就错了。同样,在new B的时候,A的构造函数被调用,但是在A的构造函数中,被调用的是A::foo()而不是B::foo()。3.3 多继承中的虚函数 3.4 什么时候使用虚函数&&&&&在你设计一个基类的时候,如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的。从设计的角度讲,出现在基类中的虚函数是接口,出现在派生类中的虚函数是接口的具体实现。通过这样的方法,就可以将对象的行为抽象化。&&&&以设计模式[2]中Factory Method模式为例,Creator的factoryMethod()就是虚函数,派生类override这个函数后,产生不同的Product类,被产生的Product类被基类的AnOperation()函数使用。基类的AnOperation()函数针对Product类进行操作,当然Product类一定也有多态(虚函数)。&&&&另外一个例子就是集合操作,假设你有一个以A类为基类的类层次,又用了一个std::vector&A *&来保存这个类层次中不同类的实例指针,那么你一定希望在对这个集合中的类进行操作的时候,不要把每个指针再cast回到它原来的类型(派生类),而是希望对他们进行同样的操作。那么就应该将这个“一样的操作”声明为virtual。&&&&现实中,远不只我举的这两个例子,但是大的原则都是我前面说到的“如果发现一个函数需要在派生类里有不同的表现,那么它就应该是虚的”。这句话也可以反过来说:“如果你发现基类提供了虚函数,那么你最好override它”。4.参考资料&[1] 深度探索C++对象模型,Stanley B.Lippman,侯捷译[2] Design Patterns, Elements of Reusable Object-Oriented Software, GOF
原文链接:C++的多态性是通过虚函数来实现的,虚函数的出现使得动态链接成为可能。
基于构造函数的特点,不能将构造函数定义为虚函数,但可以将析构函数定义为虚函数。
一般情况:当派生类的对象从内存中撤销时,会先调用派生类的析构函数,然后自动调用基类的析构函数,如此看来析构函数也没有必要定义为虚函数。
但如考虑如下这种情况,如果使用基类指针指向派生类的对象,而这个派生类对象恰好是用new运算创建的,这种情况下会如何呢?当程序使用delete运算撤销派生类对象时,这时只会调用基类的析构函数,而没有调用派生类的析构函数。如果使用的是虚析构函数的话,就不一样了,所以定义虚析构函数有时候还是很有必要的。
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:
有下面的两个类:
class ClxBase
ClxBase() {};
virtual ~ClxBase() {};
virtual void DoSomething() { cout && "Do something in class ClxBase!" && };
};class ClxDerived : public ClxBase
ClxDerived() {};
~ClxDerived() { cout && "Output from the destructor of class ClxDerived!" && };
void DoSomething() { cout && "Do something in class ClxDerived!" && };
ClxBase *pTest = new ClxD
pTest-&DoSomething();delete pT
的输出结果是:
Do something in class ClxDerived!
Output from the destructor of class ClxDerived!
这个很简单,非常好理解。
但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:
Do something in class ClxDerived!
也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
当然,并不是要把所有类的析构函数都写成虚函数。因为当类里面有虚函数的时候,编译器会给类添加一个虚函数表,里面来存放虚函数指针,这样就会增加类的存储空间。所以,只有当一个类被用来作为基类的时候,才把析构函数写成虚函数。
Note:可见,子类型化要求将析构函数声明为虚函数。特别是当析构函数完成了一些有意义的操作时,例如,关闭文件、删除指针所指向的对象等。总之,将析构函数声明为虚函数一般没有什么坏处,所以,如果不能决定是否应当将析构函数声明为虚函数时,就将析构函数声明为虚函数。
构造函数不能被声明为虚函数。因为对构造函数的调用意味着要创建一个对象,这时,必须要确切地知道这个对象的类型,而且我们也不会为一个已存在的对象调用构造函数,因此,将构造函数声明为虚函数是没有意义的。
[C++] 基类一定要定义虚析构函数
用C++写基类时注意:
1、一定要有析构函数
2、必须是虚析构函数
否则释放一个指向派生类的基类指针时,派生类的析构函数不会被调用
class CBase
C++中虚析构函数的作用及其原理分析
参考http://blog.csdn.net/xiamentingtao/article/details/
C++中的虚析构函数到底什么时候有用的,什么作用呢。
一.虚析构函数的...
C++中虚析构函数的作用
我们知道,用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。可是,为什么要这样做呢?下面用一个小例子来说明:
有下面的两个类:class ClxBase{public:...
为什么基类中的析构函数要声明为虚析构函数?
为什么基类中的析构函数要声明为虚析构函数?
用对象指针来调用一个函数,有以下两种情况:
如果是虚函数,会调用派生类中的版本。如果是非虚函数,会调用指针所指类型的实现...
基类:被其它类通过继承方式作为父类继承的类称为基类;描述派生类的统一种类的方式。
派生类:通过继承其他类(并可能含有自定义成员)实现的子类;为提高代码的重用性及与同样继承于同一个父类的其它类形成统一种...
c++中如果定义基类,要使用多态的话,基类的析构函数必须定义为虚函数,这样在析构的时候,资源才会回收干净,否则只会回收基类资源,而不会回收继承类资源。...
/*烟台大学计算机学院学生
*All right reserved.
*文件名称:体验虚基类的析构函数和虚函数
*作者:杨飞
*完成日期:日
*版本号:v1.0
*对任务及求解方法的...
(1)执行派生类的析构函数
(2)调用对象成员(子对象)的析构函数,按类声明中对象成员
出现的逆序调用,而不是初始化列表中的次序。
(3)调用普通基类的析构函数,多个基类则按...
转载:https://www.cnblogs.com/liushui-sky/p/5824919.html
& & &nb...
C++中基类的析构函数为什么要用virtual虚析构函数, 弄清楚为什么。
没有更多推荐了,C++中基类的析构函数为什么要用virtual虚析构函数 - 苦涩的茶 - 博客园
——产品开发
& & & & &要弄明白这个问题,首先要了解下C++中的动态绑定。&
& & & & &关于动态绑定的讲解,请参阅: &
& & & & &直接的讲,C++中基类采用virtual虚析构函数是为了防止内存泄漏。具体地说,如果派生类中申请了内存空间,并在其析构函数中对这些内存空间进行释放。假设基类中采用的是非虚析构函数,当删除基类指针指向的派生类对象时就不会触发动态绑定,因而只会调用基类的析构函数,而不会调用派生类的析构函数。那么在这种情况下,派生类中申请的空间就得不到释放从而产生内存泄漏。所以,为了防止这种情况的发生,C++中基类的析构函数应采用virtual虚析构函数。
示例代码讲解
现有Base基类,其析构函数为非虚析构函数。Derived1和Derived2为Base的派生类,这两个派生类中均有以string* 指向存储其name的地址空间,name对象是通过new创建在堆上的对象,因此在析构时,需要显式调用delete删除指针归还内存,否则就会造成内存泄漏。
class Base {
cout && "~Base()" &&
class Derived1 : public Base {
Derived1():name_(new string("NULL")) {}
Derived1(const string& n):name_(new string(n)) {}
~Derived1() {
delete name_;
cout && "~Derived1(): name_ has been deleted." &&
string* name_;
class Derived2 : public Base {
Derived2():name_(new string("NULL")) {}
Derived2(const string& n):name_(new string(n)) {}
~Derived2() {
delete name_;
cout && "~Derived2(): name_ has been deleted." &&
string* name_;
我们看下面对其析构情况进行测试:
int main() {
Derived1* d1 = new Derived1();
Derived2 d2 = Derived2("Bob");
delete d1;
d1为Derived1类的指针,它指向一个在堆上创建的Derived1的对象;d2为一个在栈上创建的对象。其中d1所指的对象需要我们显式的用delete调用其析构函数;d2对象在其生命周期结束时,系统会自动调用其析构函数。看下其运行结果:
刚才我们说,Base基类的析构函数并不是虚析构函数,现在结果显示,派生类的析构函数被调用了,正常的释放了其申请的内存资源。这两者并不矛盾,因为无论是d1还是d2,两者都属于静态绑定,而且其静态类型恰好都是派生类,因此,在析构的时候,即使基类的析构函数为非虚析构函数,也会调用相应派生类的析构函数。
下面我们来看下,当发生动态绑定时,也就是当用基类指针指向派生类,这时候采用delete显式删除指针所指对象时,如果Base基类的析构函数没有virtual,会发生什么情况?
int main() {
Base* base[2] = {
new Derived1(),
new Derived2("Bob")
for (int i = 0; i != 2; ++i) {
delete base[i];
& & & & 从上面结果我们看到,尽管派生类中定义了析构函数来释放其申请的资源,但是并没有得到调用。原因是基类指针指向了派生类对象,而基类中的析构函数却是非virtual的,之前讲过,虚函数是动态绑定的基础。现在析构函数不是virtual的,因此不会发生动态绑定,而是静态绑定,指针的静态类型为基类指针,因此在delete时候只会调用基类的析构函数,而不会调用派生类的析构函数。这样,在派生类中申请的资源就不会得到释放,就会造成内存泄漏,这是相当危险的:如果系统中有大量的派生类对象被这样创建和销毁,就会有内存不断的泄漏,久而久之,系统就会因为缺少内存而崩溃。
& & & & 也就是说,在基类的析构函数为非虚析构函数的时候,并不一定会造成内存泄漏;当派生类对象的析构函数中有内存需要收回,并且在编程过程中采用了基类指针指向派生类对象,如为了实现多态,并且通过基类指针将该对象销毁,这时,就会因为基类的析构函数为非虚析构函数而不触发动态绑定,从而没有调用派生类的析构函数而导致内存泄漏。
& & & & 因此,为了防止这种情况下内存泄漏的发生,最好将基类的析构函数写成virtual虚析构函数。
下面把Base基类的析构函数改为虚析构函数:
class Base {
virtual ~Base() {
cout && "~Base()" &&
再看下其运行结果:
这样就会实现动态绑定,派生类的析构函数就会得到调用,从而避免了内存泄漏。
故:&继承时,要养成的一个好习惯就是,基类析构函数中,加上virtual。
转自:http://blog.csdn.net/iicy266/article/details/
随笔 - 241C++基类函数中的virtual关键词到底表示什么意思呢_百度知道
C++基类函数中的virtual关键词到底表示什么意思呢
基类函数偶遇virtual关键词到底表示什么意思呢,表示子类可以重载么?但是如果没有virtual关键词,子类的同名函数依然可以将父类的同名函数覆盖掉,那么有没有virtual关键词根本就是一...
基类函数偶遇virtual关键词到底表示什么意思呢,表示子类可以重载么?但是如果没有virtual关键词,子类的同名函数依然可以将父类的同名函数覆盖掉,那么有没有virtual关键词根本就是一样的吧(纯虚函数除外)?
这样看的话virtual关键词主要还是用于纯虚函数么?不知道我这样理解是否正确。。
&#xe6b9;答题抽奖
首次认真答题后
即可获得3次抽奖机会,100%中奖。
采纳数:508
获赞数:993
单纯想覆盖,不需要父类写好的功能的话&确实无所谓。甚至可以说没有virtual关键字会提升一些函数调用的效率。但是假如说你子类重载的函数希望调到父类函数功能。比如class&Parent&{&&&&virtual&void&printSelf()&{&&&&&&&&cout&&&I&am&your&father&&&&&&&}};class&Son&:public&Parent{&&&&virtual&void&printSelf()&{&&&&&&&&cout&&&&son&&&&&&&&&&&Parent::printSelf();&&&&}};希望达到这样的功能,父类的函数就必须有virtual关键字。如果子类的这个函数没有virtual,那么再继承他的类就不能这样重载。
如果父类函数没有virtual关键字,子类就不能显示调用父类的函数么?
也不是。。我没解释到位。。其实用在子类中调用Parent::printSelf,无论有没有virtual关键字都可以。有virtual关键字表示他会被覆盖,在父类中调用可以调用到子类的函数。没有的话,如果在父类中调,会调父类的函数;在子类中直接调用会调用子类的函数。也就是两个函数基本是独立的都存在
tangyukuan
tangyukuan
1、基类成员函数有vitrual,子类可以重写该函数,前提是同名且参数列表和返回类型必须一致,这种情况下 通过 基类的 指针和引用调用这个virtual函数时会发生动态绑定。2、即使基类成员函数有virtual,子类也可以有同名的成员(但是参数列表不同),此时子类这个函数和基类中原有的函数是相互独立的
父类没有virtual关键字的话、子类可以用同名函数覆盖,
如果但是不能进行同名但参数不同的函数进行重载?
是这样么?
为你推荐:
其他类似问题
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。

我要回帖

更多关于 调用基类函数 的文章

 

随机推荐