C++学习(一)-虚函数(1)
2015-09-30 15:06
453 查看
1,多态性:是指不同对象收到相同的信息,产生不同的动作;简单地说,用一个名字定义不同的函数,这些函数执行不同但又类似的动作。也就是“一个接口,多钟方法”。
2,多态分为:编译时的多态和运行时的多态两种。
3,连编:是把函数名和函数体的程序代码连接在一起的过程。静态连编是在编译时完成的,动态连编是在运行时完成的,也就是在发生调用时,才去寻找和连接程序代码。
4,C++是编译性的,仍采用静态编译,但可以通过虚函数机制实现动态连编。编译时的多态性通过函数重载和运算符重载来实现。
5,(1)当基类指针指向子类对象时,基类指针调用基类和子类相同的函数时,调用的是基类的函数。
实验结果如下:
(2) 当基类的函数被设置为虚函数时,调用的子类中的函数。
实验结果如下:
(3) 当基类的虚函数带有缺省参数时时,调用的是基类中函数,即缺省参数的虚函数是静态绑定的。
实验结果如下:
以上(1),(2),(3),全都是基类对象指针指向子类对象。
(4),当子类对象指针调用基类和子类相同的函数时,调用的是子类中的函数。
实验结果如下:
(5) 子类可以继承基类的函数,并且在一定继承方式下,可以访问它,也就是说,子类没有基类同名的函数,在一定方式下,可以访问基类函数
实验结果如下:
(6),子类对象指针可以指向基类对象,但是必须强制类型转换。此时即使子类对象指针指向基类对象,在调用基类和子类相同函数时,调用的是子类函数。
实验结果:
(7),当子类指针指向基类对象时,必须强制类型转换,若基类和子类中有相同的函数,并且该函数为虚函数,用子类对象指针访问该函数时,访问的是基类中的函数。
实验结果如下:
总结:对于基类和子类中具有的相同函数,对象指针访问函数的选择,依据于其所属的类型,当该函数为虚函数;对象指针访问函数选择,依据于其指向的对象。
7,使用对象指针的目的是为了表达一种动态的性质,即当指针指向不同对象时,执行不同的操作。
8,虚函数的定义是在基类中进行的,当某个函数被定义为虚函数,其在一个或多个派生类中可以被重新定义,但是,其函数原型,包括返回值类型,函数名,形参个数,形参类型及顺序,必须与基类中原型完全相同。这也是与重载函数一个不同的地方。
9,通过定义虚函数机制来实现多态时,派生类必须从它的基类中公有继承。
10,只有通过基类指针访问虚函数,才能获得运行时的多态性。
11,一个虚函数无论被公有继承多少次,都保有虚函数的特性。
12,虚函数必须是其所在类的成员函数,不能是友元函数,也不能是静态成员函数,因为虚函数调用必须依靠指定的对象来决定该激活哪一个函数。
13,内联函数不能是虚函数,因为内联函数不能再运行时确定其位置。
14,构造函数不能是虚函数,但是析构函数可以是虚函数,并且通常是虚函数。
2,多态分为:编译时的多态和运行时的多态两种。
3,连编:是把函数名和函数体的程序代码连接在一起的过程。静态连编是在编译时完成的,动态连编是在运行时完成的,也就是在发生调用时,才去寻找和连接程序代码。
4,C++是编译性的,仍采用静态编译,但可以通过虚函数机制实现动态连编。编译时的多态性通过函数重载和运算符重载来实现。
5,(1)当基类指针指向子类对象时,基类指针调用基类和子类相同的函数时,调用的是基类的函数。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } void show() { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<" "<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show()//和基类相同的函数 { cout<<"调用的是子类函数"<<endl; cout<<"c="<<c<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); Base mc (30,20),*pb; pb=pc; //基类指针指向子类对象 //pc->show(); pb->show(); //基类指针调用基类和子类相同的函数时,调用的是基类的函数 return 0; }
实验结果如下:
(2) 当基类的函数被设置为虚函数时,调用的子类中的函数。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } virtual void show()//设置为虚函数 { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<" "<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show() { cout<<"调用的是子类函数"<<endl; cout<<"c="<<c<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); Base mc (30,20),*pb; pb=pc; //基类指针指向子类对象 //pc->show(); pb->show(); //基类指针调用基类和子类相同的函数时,调用的是子类的函数 return 0; }
实验结果如下:
(3) 当基类的虚函数带有缺省参数时时,调用的是基类中函数,即缺省参数的虚函数是静态绑定的。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } virtual void show(char* value="我是缺省参数")//基类虚函数为缺省参数 { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<" "<<value<<"\n"<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show() { cout<<"调用的是子类函数"<<endl; cout<<"c="<<c<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); Base mc (30,20),*pb; pb=pc; //基类指针指向子类对象 //pc->show(); pb->show(); //基类指针调用基类和子类相同的函数时,调用的是基类的函数 return 0; }
实验结果如下:
以上(1),(2),(3),全都是基类对象指针指向子类对象。
(4),当子类对象指针调用基类和子类相同的函数时,调用的是子类中的函数。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } void show()//和子类相同的函数 { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<"\n"<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show()//和基类相同的函数 { cout<<"调用的是子类函数"<<endl; cout<<"c="<<c<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); Base mc (30,20),*pb; //pb=pc; //基类指针指向子类对象 pc->show(); //子类对象指针调用基类和子类相同的函数时,调用的时子类的函数。 //pb->show(); return 0; }
实验结果如下:
(5) 子类可以继承基类的函数,并且在一定继承方式下,可以访问它,也就是说,子类没有基类同名的函数,在一定方式下,可以访问基类函数
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } void show() { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<"\n"<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); //子类对象指针 Base mc (30,20),*pb; //pb=pc; //基类指针指向子类对象 pc->show(); //子类对象指针调用基类函数 //pb->show(); return 0; }
实验结果如下:
(6),子类对象指针可以指向基类对象,但是必须强制类型转换。此时即使子类对象指针指向基类对象,在调用基类和子类相同函数时,调用的是子类函数。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } void show() { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<"\n"<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show() { cout<<"调用的是子类函数"<<endl; //cout<<c<<"\n"<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); //子类对象指针 Base mc (30,20),*pb; pc=(Derived*)&mc; //子类对象指针指向基类对象 pc->show(); //子类对象指针调用子类函数 //pb->show(); return 0; }
实验结果:
(7),当子类指针指向基类对象时,必须强制类型转换,若基类和子类中有相同的函数,并且该函数为虚函数,用子类对象指针访问该函数时,访问的是基类中的函数。
#include "stdafx.h" #include "iostream" using namespace std; class Base { public: Base(int x,int y) { a=x; b=y; } virtual void show()//设置为虚函数 { cout<<"调用的是基类函数"<<endl; cout<<a<<" "<<b<<"\n"<<endl; } private: int a; int b; }; class Derived:public Base { public: Derived(int x,int y,int z):Base(x,y) { c=z; } void show() { cout<<"调用的是子类函数"<<endl; //cout<<c<<"\n"<<endl; } private: int c; }; int main() { Derived *pc=new Derived(30,50,40); //子类对象指针 Base mc (30,20),*pb; pc=(Derived*)&mc; //子类对象指针指向基类对象 pc->show(); //子类对象指针调用基类函数 //pb->show(); return 0; }
实验结果如下:
总结:对于基类和子类中具有的相同函数,对象指针访问函数的选择,依据于其所属的类型,当该函数为虚函数;对象指针访问函数选择,依据于其指向的对象。
7,使用对象指针的目的是为了表达一种动态的性质,即当指针指向不同对象时,执行不同的操作。
8,虚函数的定义是在基类中进行的,当某个函数被定义为虚函数,其在一个或多个派生类中可以被重新定义,但是,其函数原型,包括返回值类型,函数名,形参个数,形参类型及顺序,必须与基类中原型完全相同。这也是与重载函数一个不同的地方。
9,通过定义虚函数机制来实现多态时,派生类必须从它的基类中公有继承。
10,只有通过基类指针访问虚函数,才能获得运行时的多态性。
11,一个虚函数无论被公有继承多少次,都保有虚函数的特性。
12,虚函数必须是其所在类的成员函数,不能是友元函数,也不能是静态成员函数,因为虚函数调用必须依靠指定的对象来决定该激活哪一个函数。
13,内联函数不能是虚函数,因为内联函数不能再运行时确定其位置。
14,构造函数不能是虚函数,但是析构函数可以是虚函数,并且通常是虚函数。
相关文章推荐
- leetcode 258 :Add Digits
- C语言使用正则表达式
- C语言中的异常处理机制
- 笔记-C语言-第三节-循环结构
- c++实现单向链表
- c++实现des算法
- C++继承中关于子类构造函数的写法
- HDOJ A+B 问题
- 指针和const
- C++ 11 右值引用
- 【Python3】error: Microsoft Visual C++ 10.0 is required 错误解决办法
- C++中的单例模式
- 裴波那契数列 C++版
- Item 38:通过组合表示"拥有"或"以...实现"的关系 Effective C++笔记
- C++_虚析构函数
- duilib JS与C++的相互调用
- Java/C++_类的默认的初始值
- eclipse编写C/C++语言
- obeject-c语言简介、基础语法
- 变量(对象)“生命期”和“作用域”的关系