虚函数重要性质总结

我们经常用虚函数完成运行时的类函数多态行为。这是很基本的了。

 

但是我们想这样一个问题?

如果我们想我们的类层次结构实现一个函数多态,那么我们就会想着为我们类层次结构中的基类添加虚函数,然后派生类依次重写。

但是不是只有直接调用虚函数才能实现多态行为呢?

 

别忘了,我们函数之间是可以相互调用的,你也看到我说的是直接。所以,我们可以通过基类一个普通函数,让此普通函数调用虚函数,实现派生类直接调用基类普通函数实现多态。这些东西说起来很简单。但实际相灵活运用,并且用的恰到好处,那可是需要很高的水平啊。其实以上提的这两种方法本质都是利用了虚函数的多态行为。但是后一种也时常在实际的使用,而初学者也经常会误会,搞不懂其中的玄机。

 

类切割注意点

class A
{
public:
 A(){cout<<"A's default construction is invoked!"<<endl;}
 ~A(){cout<<"A's destruction is invoked!"<<endl;}
 A( const A& rhs ){cout<<"A's copy construction is invoked!"<<endl;}
 virtual void Show() const{cout<<"A's Show"<<endl;}
};

class B:public A
{
public:
 B(){cout<<"B's construction is invoked!"<<endl;}
 ~B(){cout<<"B's destruction is invoked!"<<endl;}
 virtual void Show() const {cout<<"B's Show"<<endl;}
};

main()
{
    B b;
    ((A)b).Show();
}

其输出时什么呢?

 

答案是:

A's default construction is invoked!
B's construction is invoked!
A's copy construction is invoked!
A's Show
A's destruction is invoked!
B's destruction is invoked!
A's destruction is invoked!

 

原因是:((A)b)是C++重要的对象切割,这种切割会把b对象产生临时A类对象。是一个全新的对象,所以调用的虚函数是A类的。

 

如果在main()

{

    B b;

    ((A&)b).Show();

}

其输出时什么呢?

 

答案是:

A's default construction is invoked!
B's construction is invoked!
B's Show
B's destruction is invoked!
A's destruction is invoked!

原因是:((A&)b)相当于把b传递给A&的一个匿名对象,由于引用所以没有创建新对象,还是原来对象的另一个别名,同时具有指针的多态性质。

 

另外容易混淆的是:在类函数中以类作用域符号调用虚函数方式将不会有多态性之,而是单纯的调用对应类的对应函数。切记!

时间: 2024-09-20 05:44:28

虚函数重要性质总结的相关文章

C#的虚函数解析机制

前言 这篇文章出自我个人对C#虚函数特性的研究和理解,未参考.查阅第三方资料,因此很可能存在谬误之处.我在这里只是为了将我的理解呈现给大家,也希望大家在看到我犯了错误后告诉我. 用词约定 "方法的签名"包括返回类型.方法名.参数列表,这三者共同标识了一个方法. "声明方法",即指出该方法的签名."定义方法",则是指定调用方法时执行的代码. "同名方法"是指方法的签名相同的两个方法. "重写"一个方法,意味着

MFC浅析(7) CWnd类虚函数的调用时机、缺省实现 .

1. Create 2. PreCreateWindow 3. PreSubclassWindow 4. PreTranslateMessage 5. WindowProc 6. OnCommand 7. OnNotify 8. OnChildNotify 9. DefWindowProc 10. DestroyWindow 11. PostNcDestroy CWnd作为MFC中最基本的与窗口打交道的类,完成了大部分窗口管理任务.同时提供了很多虚拟函数,这些虚拟函数在适当的地方提供了供派生类参

class-关于const虚函数问题,求解

问题描述 关于const虚函数问题,求解 class Base { public: virtual void print() const = 0; }; class Test : public Base { public: void print() {cout << "Test::print()" << endl;} void print() const { cout << "Test::print() const" <&l

有关基类指针调用类的虚函数时所遇到的问题

问题描述 有关基类指针调用类的虚函数时所遇到的问题 下列输出中其中一个第2处为什么无法输出相应字符串?并且当类中的输出字符串改为输出int 类型age时又为什么可以? 问题1:问题2: 解决方案 忽视了作用域

java和c++比较(1)--虚函数和指针

c++|比较|函数    1.java中有虚函数,但是没指针,那也许会有这样的问题,那java是怎么实现多态的? java中可以肯定是有虚函数的,而且我们如果不申明为final形他默认就是虚函数.不用vitual申明. "In Java, you do not need to declare a method as virtual. Dynamic binding is the default behavior. If you do not want a method to be virtual

C#中虚函数,抽象,接口的简单说明

函数 虚函数:由virtual声明,它允许在派生类中被重写,要重写方法,必须先声名为virtual public class myclass { public virtual int myint() { 函数体: } } class myclass1:myclass { public override int myint() { 函数体1: } } 抽象类.抽象函数:由abstract声明,在抽象类中可以定义抽象方法,抽象方法基本没有执行代码,派生类必须重写它,提供其执行代码 public ab

C++中的纯虚函数(pure virtual) 和抽象基类(abstract base class)

纯虚函数(pure virtual), 是一个基类中的方法, 仅仅是声明, 而不包括定义, 是一个泛化概念(general concept); 是把相应的虚函数, 末尾添加"=0",该虚函数就变为纯虚函数, 可以不用添加定义; 如果是其他虚函数, 即使不使用, 也必须定义(define); 包含纯虚函数的基类, 是抽象基类(abstract base class),不能定义(define)对象(object), 仅可以作为继承使用; 代码: /* * CppPrimer.cpp * *

C++中虚函数(virtual function) 的 使用范围

虚函数(virtual function) 在 基函数(base function) 和 派生函数(derived function) 之间可以覆写(override); 如果派生函数有与虚函数同名的函数, 则会隐藏虚函数, 但是虚函数还会在; 由于派生对象和基对象可以转换, 可以只使用基对象部分; 派生对象的虚函数会覆写基对象的虚函数; 代码: /* * cppprimer.cpp * * Created on: 2013.11.13 * Author: Caroline */ /*eclip

C++中如何在容器中使用继承和虚函数

容器不支持混合类型, 如果直接把派生类对象, 存入基类容器中, 则无法使用派生-基转换(derived-base conversion); 因为转换只能发生在指针和引用 过程中, 不能发生在 对象直接赋值, 如果是直接转换, 则会产生截断(sliced down); 即派生类部分被切除, 只留下基类部分; 所以存入容器中的派生类 输出为基类部分 的虚函数; 如果想在容器中, 进行继承, 则需要使用指针, 包括智能指针(如:shared_ptr<>), 则会输出派生类的覆写(override)版