C++基础4:多态
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C++基础4:多态,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含19599字,纯文字阅读大概需要28分钟。
内容图文
文章目录
(***)1.定义&功能
多态:不同类型对象调用相同接口完成不同的行为。
a.问题:同名,同参函数出现同名隐藏,仅仅显示父类
Func(c1); //Animal
Func(c2); //Animal
Func(d1); //Animal
Func(d2); //Animal
(完整代码000_same_name.cpp)
#include <iostream>
using namespace std;
class Animal{
public:
string GetName(){
return "Animal";
}
};
class Cat:public Animal{
public:
string GetName(){
return "Cat";
}
};
class Dog:public Animal{
public:
string GetName(){
return "Dog";
}
};
void Func(Animal& a){ //同名,同参函数出现同名隐藏,仅仅显示父类,必须要传引用或者指针
cout << a.GetName() << endl;
}
int main(){
Cat c1;
Cat c2;
Dog d1;
Dog d2; //a.同名,同参函数出现同名隐藏,仅仅显示父类
Func(c1); //Animal
Func(c2); //Animal
Func(d1); //Animal
Func(d2); //Animal
}
b1.(引用示例)父类函数加入virtual,即可以实现不同对象的相同功能,必须要传对象的引用或者对象的指针(引用示例)
virtual string GetName(){ //b.父类函数加入virtual,即可以实现不同对象的相同功能
void Func(Animal& a){
cout << a.GetName() << endl;
}
(完整代码00101_override.cpp)
#include <iostream>
using namespace std;
class Animal{
public:
virtual string GetName(){ //b.父类函数加入virtual,即可以实现不同对象的相同功能
return "Animal";
}
};
class Cat:public Animal{
public:
string GetName(){
return "Cat";
}
};
class Dog:public Animal{
public:
string GetName(){
return "Dog";
}
};
void Func(Animal& a){
cout << a.GetName() << endl;
}
int main(){
Cat c1;
Cat c2;
Dog d1;
Dog d2;
Func(c1); //Cat
Func(c2); //Cat
Func(d1); //Dog
Func(d2); //Dog
}
b2.(指针示例)父类函数加入virtual,即可以实现不同对象的相同功能,必须要传对象的引用或者对象的指针(指针示例)
//(1)class
void Func(Animal* p){
cout << p->GetName() << endl;
}
//(2)main()
Func(&c1);
Func(&c2);
Func(&d1);
Func(&d2);
(完整代码00102_overload.cpp)
#include <iostream>
#include <vector>
using namespace std;
class Animal{
public:
virtual string GetName(){
return "动物";
}
};
class Cat:public Animal{
public:
virtual string GetName(){
return "猫";
}
};
class Dog:public Animal{
public:
string GetName(){
return "狗";
}
};
void Func(Animal* p){
cout << p->GetName() << endl;
}
int main(){
Cat c1;
Cat c2;
Dog d1;
Dog d2;
Func(&c1);
Func(&c2);
Func(&d1);
Func(&d2);
}
c1.(数组示例)单一对象,单一打印,多个对象需要用数组或者向量(注意没有引用数组);
Animal* arr[] = {&c1,&c2,&d1,&d2};
for(int i=0;i<4;++i){
cout << arr[i]->GetName() << endl;
}
(完整代码 00201_datebank_overload.cpp)
#include <iostream>
#include <vector>
using namespace std;
class Animal{
public:
Animal(){}
Animal(const Animal&){cout << "Copy Construct"<<endl;}
// 1. 继承
// 2. 有函数名和参数完全相同的函数,并且父类函数前有关键字virtual
// 3. 子类对象赋值给父类的指针或者引用
virtual string GetName(){
return "动物";
}
};
class Cat:public Animal{
public:
virtual string GetName(){
return "猫";
}
};
class Dog:public Animal{
public:
string GetName(){
return "狗";
}
};
/*
void Func(Animal& a){
cout << a.GetName() << endl;
}
*/
void Func(Animal a){
cout << a.GetName() << endl;
}
void Func(Animal* p){
cout << p->GetName() << endl;
}
int main(){
Cat c1;
Cat c2;
Dog d1;
Dog d2;
cout << c1.GetName() << endl;
cout << c2.GetName() << endl;
cout << d1.GetName() << endl;
cout << d2.GetName() << endl;
Func(&c1);
Func(&c2);
Func(&d1);
Func(&d2);
Animal* arr[] = {&c1,&c2,&d1,&d2};
// Animal& arr[] = {c1,c2,d1,d2};
// vector<Animal*> arr = {&c1,&c2,&d1,&d2};
// vector<Animal&> arr = {c1,c2,d1,d2};
for(int i=0;i<4;++i){
cout << arr[i]->GetName() << endl;
}
}
c2.(vector示例)单一对象,单一打印,多个对象需要用数组或者向量(注意没有引用数组);g++ *.cpp -std=c++11
vector<Animal*> arr = {&c1,&c2,&d1,&d2};
// vector<Animal&> arr = {c1,c2,d1,d2};
for(int i=0;i<4;++i){
cout << arr[i]->GetName() << endl;
}
#include <iostream>
#include <vector>
using namespace std;
class Animal{
public:
Animal(){}
Animal(const Animal&){cout << "Copy Construct"<<endl;}
// 1. 继承
// 2. 有函数名和参数完全相同的函数,并且父类函数前有关键字virtual
// 3. 子类对象赋值给父类的指针或者引用
virtual string GetName(){
return "动物";
}
};
class Cat:public Animal{
public:
virtual string GetName(){
return "猫";
}
};
class Dog:public Animal{
public:
string GetName(){
return "狗";
}
};
/*
void Func(Animal& a){
cout << a.GetName() << endl;
}
*/
void Func(Animal a){
cout << a.GetName() << endl;
}
void Func(Animal* p){
cout << p->GetName() << endl;
}
int main(){
Cat c1;
Cat c2;
Dog d1;
Dog d2;
cout << c1.GetName() << endl;
cout << c2.GetName() << endl;
cout << d1.GetName() << endl;
cout << d2.GetName() << endl;
Func(&c1);
Func(&c2);
Func(&d1);
Func(&d2);
// Animal* arr[] = {&c1,&c2,&d1,&d2};
// Animal& arr[] = {c1,c2,d1,d2};
vector<Animal*> arr = {&c1,&c2,&d1,&d2};
// vector<Animal&> arr = {c1,c2,d1,d2};
for(int i=0;i<4;++i){
cout << arr[i]->GetName() << endl;
}
}
d.(***)向量,数组,定义的时候不调用拷贝构造函数;
但是填充对象的时候需要调用拷贝构造函数;
不填充对象,只开辟空间需要调用默认构造函数;
如果调用的函数里面还有important
vector<Simple> vec; //0
vec.push_back(s); //1
vector<Simple> vec1(5,s); //5--copy
vector<Simple> vec2(5); //5--default
(完整代码 003_vector_arr_construct.cpp)
#include <iostream>
using namespace std;
#include <vector>
class Simple{
public:
Simple(){cout <<"default"<<endl;}
Simple(const Simple&){cout << "copy"<< endl;}
Simple& operator=(const Simple&){cout<<"operator"<<endl;}
~Simple(){cout<<"Free"<<endl;}
};
int main(){
Simple s;
vector<Simple> vec;
vec.push_back(s);
cout << &s << endl;
cout << &vec.front() << endl;
cout << &vec[0] << endl;
vector<Simple> vec1(5,s); //copy 5
vector<Simple> vec2(5); //default 5
cout << "____" <<endl;
Simple sim[] = {s};
}
根据对象的实际类型不同,可以自动完成不同的行为,而仅仅通过一致的调用形式。
2. 关系
没有封装就不能继承,没有继承就没有运行时的多态。
早绑定/overload | 晚绑定/override |
---|---|
函数和运算符重载 | 继承与虚函数 |
绑定
|早绑定/overload|晚绑定/override
函数和运算符重载|继承与虚函数
(***)3.覆盖(重写override)与虚函数的使用
- 覆盖成立的三个条件
a…条件一:继承
class Son:public Father{
b.条件2:子类覆盖(重写)父类虚函数
void func(){
cout << "son " << endl;
}
c.条件三:父类指针/引用指向子类
Father* fpt =&s;
fpt ->func();
Father& fpr = s;
fpr.func();
d1(其他)三种调用的对比
Father f;
f.func();//a.类内引用
Son s;
s.func(); //b1.子类的类内引用(实质:同名隐藏)
Son* ps = &s;
ps-> func(); //b2.子类的类内引用(实质:同名隐藏)
Father* fpt =&s;
fpt ->func(); //c1.多态
Father& fpr = s;
fpr.func(); //c2.多态
(完整代码 005_override.cpp)
#include <iostream>
using namespace std;
class Father{
public:
virtual void func(){
cout << "father " << endl;
}
};
class Son:public Father{ //1..继承
public:
void func(){
cout << "son " << endl; // 2.子类覆盖(重写)父类虚函数
}
};
int main(){
Father f;
f.func();//a.类内引用
Son s;
s.func(); //b1.子类的类内引用(实质:同名隐藏)
Son* ps = &s;
ps-> func(); //b2.子类的类内引用(实质:同名隐藏)
Father* fpt =&s;
fpt ->func(); //c1.多态 c.父类指针/引用指向子类
Father& fpr = s;
fpr.func(); //c2.多态 c.父类指针/引用指向子类
}
d2.
d2.1.同名隐藏:(1)是否去除隐藏,去除并重写,则是子类;去除未重写&未去除隐藏,则是父类;
B b;
b.Func(); //已经去除了同名隐藏,可以是子类的;
b.Func(1); //同名隐藏;
d2.2类内拷贝,查看类是子类还是父类,调用者就是谁;
A a(b);
a.Func();
a.Func(2); //重载函数,正常调用,因为是父类型
d2.3.重写,需要满足三个条件,
A* pa = &b; //覆盖
pa->Func(); //子类
pa->Func(4); //子类
(完整代码006_override.cpp)
#include <iostream>
using namespace std;
class A{
public:
virtual void Func(){
cout << "A::Func()" << endl;
}
void Func(int n){
cout << "A::Func( " << n << " )" << endl;
}
};
class B:public A {
public:
using A::Func;
void Func(){
cout << "B::Func()" << endl;
}
};
int main(){
B b;
b.Func(); //已经去除了同名隐藏,可以是子类的;
b.Func(1); //同名隐藏;
A a(b);
a.Func();
a.Func(2); //重载函数,正常调用,因为是父类型
A c;
c = b; //同上;
c.Func();
c.Func(3);
A* pa = &b; //覆盖
pa->Func(); //子类
pa->Func(4); //子类
A& fa = b;
fa.Func();
fa.Func(5); //同上
return 0;
}
(***)4.多态产生的效果
-
同样的调用语句实现不同的表现,框架的基石,设计模式的基础。
-
虚函数定义规则:
1.如果虚函数在基类与派生类中出现,仅仅是名字相同,而形式参数不同,或者是返回类型不同,有无const
.那么即使加上了virtual
关键字,子类最好也加上virtual
,也是不会覆盖。
2.只有类的成员函数才能说明为虚函数,因为虚函数仅适合用与有继承关系的类对象,所以普通函数不能说明为虚函数。
3.静态成员函数不能是虚函数,因为静态成员函数的特点是不受限制于某个对象。
4.内联(inline
)函数不能是虚函数,因为内联函数不能在运行中动态确定位置。即使虚函数在类的内部定义,但是在编译的时候系统仍然将它看做是非内联的。
***5.构造函数不能是虚函数,因为构造的时候,对象还是一片未定型的空间,只有构造完成后,对象才是具体类的实例。
***6.析构函数可以是虚函数,而且通常声明为虚函数,父类的析构函数必须是虚函数。
***7.子类以
new
方式实例化,指针赋值给父类指针,delete
父类指针时,只调用父类的析构函数,不调用子类的析构函数,出现没有释放的空间;。
解决:在父类的析构函数前面加上virtual;
a.父类的析构函数是虚函数;子类的析构函数最好写成虚函数;
virtual ~Father()
virtual ~Son()
(完整代码007_virtual_father.cpp)
#include <iostream>
using namespace std;
class Father{
public:
Father(){
cout << "Default Father"<<endl;
}
virtual ~Father(){ //a.父类的析构函数是虚函数;
cout << "~Father"<<endl;
}
};
class Son: public Father{
public:
Son(){
cout << "Default Son"<<endl;
}
virtual ~Son(){ //a.子类的析构函数最好写成虚函数;
cout << "~Son"<<endl;
}
};
int main(){
Father* pf2 = new Son;
delete pf2;
}
- 多态的实现原理分析
当类中声明虚函数时,编译器会在类中生成一个虚函数表(基类和派生类中各自都会生成一个)
虚函数表
虚函数表是一个存储类成员函数指针的数据结构
虚函数表是由编译器自动生成和维护的
virtual
函数会被编译器放入虚函数表中
存在虚函数时,每个对象当中都有一个指向虚函数表的指针(vptr指针)
(***)5.纯虚函数
a.基类声明的时侯后面 加 =0;
class 类名{
virtual 返回值类型 函数(形参列表) = 0;
}
b.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
virtual float GetLength(){return a+b+c;} //b.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
virtual float GetArea(){ //纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
float half = GetLength()/2.0;
return sqrt(half*(half-a)*(half-b)*(half-c));
}
c.用的时候可以用 new,delete;会调用析构函数;
Shape* arr[] = {
new Triangle(3,4,5),
new Circle(2),
new Rect(4,5)
};
for(int i = 0;i<3;++i){
delete arr[i];
}
}
d. .子类必须继承父类的所有纯虚函数,可以return 0;
virtual float GetArea(){ // d. .子类必须继承父类的所有纯虚函数,可以return 0;
return 0;
}
(完整代码1 008_virtual.cpp)
#include <iostream>
#include <cmath>
using namespace std;
class Shape{
public:
virtual float GetLength() = 0; //a基类声明的时侯后面 加 =0;
virtual float GetArea() = 0; // a基类声明的时侯后面 加 =0;
virtual ~Shape(){cout << __func__ <<endl;}
};
class Triangle:public Shape{
float a,b,c;
public:
Triangle(float a,float b, float c):a(a),b(b),c(c){}
virtual float GetLength(){return a+b+c;} //b.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
virtual float GetArea(){ //纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
float half = GetLength()/2.0;
return sqrt(half*(half-a)*(half-b)*(half-c));
}
~Triangle(){cout<<__func__<<endl;}
};
class Circle:public Shape{
private:
float r;
public:
Circle(float r):r(r){}
virtual float GetLength(){
return 2*M_PI*r;
}
virtual float GetArea(){
return M_PI*r*r;
}
~Circle(){cout<<__func__<<endl;}
};
class Rect: public Shape{
private:
float a, b;
public:
Rect(float a, float b):a(a),b(b){}
virtual float GetLength(){
return (a+b)*2;
}
virtual float GetArea(){
return a*b;
}
~Rect(){cout<<__func__<<endl;}
};
int main(){
Shape* arr[] = {
new Triangle(3,4,5),
new Circle(2),
new Rect(4,5)
}; //用的时候可以用 new,delete;会调用析构函数;
float sumLength =0;
float sumArea =0;
for(int i = 0; i< 3;++i){
float Length = arr[i]->GetLength();
float Area = arr[i]->GetArea();
cout << Length << endl;
sumLength += Length;
sumArea += Area;
}
cout << sumLength << endl;
cout << sumArea << endl;
for(int i = 0;i<3;++i){
delete arr[i]; //用的时候可以用 new,delete;会调用析构函数;
}
}
(完整代码2 009_abstract.cpp)
#include <iostream>
#include <cmath>
using namespace std;
class Shape{
public:
virtual float GetLength() = 0; //a基类声明的时侯后面 加 =0;
virtual float GetArea() = 0; // a基类声明的时侯后面 加 =0;
virtual ~Shape(){cout << __func__ <<endl;}
};
class Triangle:public Shape{
float a,b,c;
public:
Triangle(float a,float b, float c):a(a),b(b),c(c){}
virtual float GetLength(){return a+b+c;} //b.纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
virtual float GetArea(){ //纯虚函数是在基类中声明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。
float half = GetLength()/2.0;
return sqrt(half*(half-a)*(half-b)*(half-c));
}
~Triangle(){cout<<__func__<<endl;}
};
class Circle:public Shape{
private:
float r;
public:
Circle(float r):r(r){}
virtual float GetLength(){
return 2*M_PI*r;
}
virtual float GetArea(){
return M_PI*r*r;
}
~Circle(){cout<<__func__<<endl;}
};
class Rect: public Shape{
private:
float a, b;
public:
Rect(float a, float b):a(a),b(b){}
virtual float GetLength(){
return (a+b)*2;
}
virtual float GetArea(){
return a*b;
}
~Rect(){cout<<__func__<<endl;}
};
class Line: public Shape{
private:
float StartX,StartY,EndX,EndY;
public:
Line(float StartX, float StartY,float EndX, float EndY): StartX( StartX), StartY(StartY),EndX(EndX), EndY(EndY){}
virtual float GetLength(){
float CalX = StartX - EndX;
float CalY = StartY - EndY;
return sqrt(CalX*CalX + CalY*CalY);
}
virtual float GetArea(){ // d. .子类必须继承父类的所有纯虚函数,可以return 0;
return 0;
}
~Line(){cout<<__func__<<endl;}
};
int main(){
// Shape s; a.包含纯虚函数的类是抽象类,继承的类可能是抽象类;都不能实例化对象;
// Line l;
Shape* arr[] = {
new Triangle(3,4,5),
new Circle(2),
new Rect(4,5),
new Line(0,0,1,1)
}; //用的时候可以用 new,delete;会调用析构函数;
float sumLength =0;
float sumArea =0;
for(int i = 0; i< 4;++i){
float Length = arr[i]->GetLength();
float Area = arr[i]->GetArea();
cout << Length << endl;
sumLength += Length;
sumArea += Area;
}
cout << sumLength << endl;
cout << sumArea << endl;
for(int i = 0;i<4;++i){
delete arr[i]; //用的时候可以用 new,delete;会调用析构函数;
}
}
- 抽象类
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。
继承抽象类仍然可能是抽象类 .
纯虚函数可以写函数体,但是不可能被调用.
Shape s; // a.包含纯虚函数的类是抽象类,继承的类可能是抽象类;都不能实例化对象;
Line l;
(完整代码见上009_abstract.cpp)
在很多C++书籍上没有覆盖(overrride)这种称谓,而是直接称为多态(polymorphism)。例如:《C++Primer》、《设计模式》、《C++对象模型》、《深入浅出MFC》等。
维基百科polymorphism
Polymorphism can be distinguished by when the implementation is selected: statically (at compile time) or dynamically (at run time, typically via a virtual function).
(***)6小结:重载+重写
- 重载覆盖的区别
No. | 重载 | 覆盖 |
---|---|---|
1 | 重载要求函数名相同,但是参数列表必须不同,返回值可以相同也可以不同。 | 覆盖要求函数名、参数列表、返回值必须相同。 |
2 | 在类中重载是同一个类中不同成员函数之间的关系。 | 在类中覆盖则是子类和基类之间不同成员函数之间的关系。 |
3 | 重载函数的调用是根据参数列表决定。 | 覆盖函数的调用是根据对象类型决定。 |
4 | 重载函数是在编译时确定调用一个函数。 | 覆盖函数是在执行时确定调用个函数。 |
a.覆盖特殊情况:如果覆盖函数的返回类型是具有继承关系的类指针,引用类型,虽然类型不同,但是仍然是覆盖;
virtual B* Func() const{
//覆盖特殊情况:如果覆盖函数的返回类型是具有继承关系的类指针,引用类型,虽然类型不同,但是仍然是覆盖;
(完整代码 010_override.cpp)
#include <iostream>
using namespace std;
class A {
public:
virtual A* Func() const{
cout << "A" << endl;
return NULL;
}
};
class B: public A{
public:
virtual B* Func() const{
//覆盖特殊情况:如果覆盖函数的返回类型是具有继承关系的类指针,引用类型,虽然类型不同,但是仍然是覆盖;
cout << "B" << endl;
return NULL;
}
};
int main(){
B b;
A* p = &b;
p->Func();
}
- 代码如何判断是否调用了覆盖函数
a.用上面的步骤进行判断
(完整代码006_override.cpp)
#include <iostream>
using namespace std;
class A{
public:
virtual void Func(){
cout << "A::Func()" << endl;
}
void Func(int n){
cout << "A::Func( " << n << " )" << endl;
}
};
class B:public A {
public:
using A::Func;
void Func(){
cout << "B::Func()" << endl;
}
};
int main(){
B b;
b.Func(); //已经去除了同名隐藏,可以是子类的;
b.Func(1); //同名隐藏;
A a(b);
a.Func();
a.Func(2); //重载函数,正常调用,因为是父类型
A c;
c = b; //同上;
c.Func();
c.Func(3);
A* pa = &b; //覆盖
pa->Func(); //子类
pa->Func(4); //子类
A& fa = b;
fa.Func();
fa.Func(5); //同上
return 0;
}
- b父类指针的两种用法,结果是derive
(完整代码 011_override.cpp)
Base* pB = new Derive; //父类指针指向子类
pB->Func(); //指针的写法1
(*pB).Func(); //指针的写法2
#include <iostream>
using namespace std;
class Base{
public:
virtual void Func()const{ cout << "Base" << endl; }
};
class Derive : public Base {
public:
void Func() const { cout << "Derive" << endl; }
};
int main() {
Base* pB = new Derive; //父类指针指向子类
pB->Func(); //指针的写法1
(*pB).Func(); //指针的写法2
}
- c. (友元函数—全局的结果调用的是父类,不符合重写里面的virtual继承),结果为Base
friend ostream& operator<<(ostream& os,const Base& b){ return os << "Base"; }
Base* pB = new Derive;
};
(完整代码 012_friend_override.cpp)
#include <iostream>
using namespace std;
class Base{
public:
friend ostream& operator<<(ostream& os,const Base& b){ return os << "Base"; }
};
class Derive : public Base {
public:
friend ostream &operator<<(ostream &os, const Derive &b) { return os << "Derive"; }
};
int main() {
Base* pB = new Derive;
cout << (*pB) << endl;
}
d. 双重转发(Double Dispatch)
a1.先根据指针找到友元函数的引用;
Base* pB = new Derive; //a1.先根据指针找到友元函数的引用;
a2。返回put虚拟继承函数;
friend ostream &operator<<(ostream &os,const Base &b) {return b.Put(os);}
};//a2。返回put虚拟继承函数;
a3.进行虚函数的双重转发(重写)
virtual ostream &Put(ostream &os) const { return os << "Base"; } //a3.进行虚函数的双重转发(重写)
(完整代码 013_doubleDispatch.cpp)
#include <iostream>
using namespace std;
class Base{
public:
virtual ostream &Put(ostream &os) const { return os << "Base"; } //a3.进行虚函数的双重转发(重写)
friend ostream &operator<<(ostream &os,const Base &b) {return b.Put(os);}
};//a2。返回put虚拟继承函数;
class Derive : public Base {
public:
ostream &Put(ostream &os) const { return os << "Derive"; }
friend ostream &operator<<(ostream &os, const Derive &b) { return b.Put(os); }
};
int main() {
Base* pB = new Derive; //a1.先根据指针找到友元函数的引用;
cout << (*pB) << endl;
}
e.多重继承(从第一个virtual进行判断override的三个条件)
情况一:a.从头开始虚函数重写,(C)
class A{
public:
virtual void Func(){
cout << "A" << endl;
}
};
b.可以进行传递;覆盖
A* a = new C; //可以进行传递;覆盖
(完整代码 01401_mutiextend.cpp)
#include <iostream>
using namespace std;
class A{
public:
virtual void Func(){
cout << "A" << endl;
}
};
class B:public A{
public:
void Func(){ //虚函数从继承关系中,第一个定义虚函数的继承类开始覆盖;
cout << "B" << endl;
}
};
class C:public B{
public:
virtual void Func(){ //C的基类已经覆盖了A的虚函数,那么C继承的虚函数是覆盖过的;
cout << "C" << endl;
}
};
int main(){
A* a = new C; //可以进行传递;覆盖
a->Func();
}
情况二。虚函数继承从中间开始继承,重写,不可以进行传递;必须是B,C之间的指针;否则为当前类的调用;(A)
A* a = new C; //不可以进行传递;必须是B,C之间的指针;否则为当前类的调用;
(完整代码 01402_mutiextend.cpp)
#include <iostream>
using namespace std;
class A{
public:
void Func(){
cout << "A" << endl;
}
};
class B:public A{
public:
virtual void Func(){ //a.虚函数继承从中间开始继承
cout << "B" << endl;
}
};
class C:public B{
public:
void Func(){ //
cout << "C" << endl;
}
};
int main(){
A* a = new C; //不可以进行传递;必须是B,C之间的指针;否则为当前类的调用;
a->Func();
}
Pierce110110
发布了35 篇原创文章 · 获赞 8 · 访问量 3830
私信
关注
内容总结
以上是互联网集市为您收集整理的C++基础4:多态全部内容,希望文章能够帮你解决C++基础4:多态所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。