(1):解释多态性:
函数的多种不同的实现方式即为多态
(2):必要性
在继承中,有时候基类的一些函数在派生类中也是有用的,但是功能不够全或者两者的功能实现方式就是不一样的,这个时候就希望重载那个基类的函数,但是为了不再调用这个函数时,出现不知道调用基类的还是子类的情况出现,于是就提出了多态。如果语言不知多态,则不能称为面向对象的。
(3):多态性是如何实现的
多态是实现是依赖于虚函数来实现的,之所以虚函数可以分清楚当前调用的函数是基类的还是派生类的,主要在于基类和派生类分别有着自己的虚函数表,再调用虚函数时,它们是通过去虚函数表去对应的函数的。
参考代码如下:
#include<iostream>
using namespace std;
class A
{
public :
void print()
{
cout << "A" << endl;
}
virtual void print1()
{
cout << "Virtual A" << endl;
}
};
class B:public A{
public:
void print() { cout << "B" << endl; }
virtual void print1() { cout << "Virtual B" << endl; }
};
void fn(A & s)
{
s.print();
s.print1();
}
int main()
{
A a;
B b;
fn(a);
fn(b);
return 0;
}
我们可以看出在使用了虚函数之后,程序就只当前该调用哪个类的函数了。其实虚函数表的本质就是一种迟后联编的过程,正常编译都是先期联编的,但是当代码遇到了virtual时,就会把它当做迟后联编,但是为了迟后编译,我么就生成了局部变量–虚函数表,这就增大了一些空间上的消耗。(前提是两个函数的返回类型,参数类型,参数个数都得相同,不然就起不到多态的作用)
再来看一个例子:
#include<iostream>
#include<cmath>
using namespace std;
class A
{
public :
virtual void fun(int x)
{
cout << "A: " << x << endl;
}
};
class B :public A
{
public :
virtual void fun(float x)
{
cout << "B: " << x << endl;
}
};
void test(A & x)
{
int i = 1;
x.fun(i);
float a = 2.0;
x.fun(a);
}
int main()
{
A a;
B b;
test(a);
test(b);
return 0;
}
从输出结果可以看出,fun函数并没有起到多态的作用,这里主要是因为基类和派生类的fun在编译时,被看成了两个不同函数,因为他们的参数不同。如果返回的类型不同,也会出现同样的情况,但是有一种特殊的情况,那就是如果基类中虚函数返回一个基类指针或引用,派生类中返回一个派生类的指针或引用,则c++将其视为同名虚函数而进行迟后联编。
#include<iostream>
#include<cmath>
using namespace std;
class A
{
public :
virtual A * fun()
{
cout << "A: " << endl;
return this;
}
};
class B :public A
{
public :
virtual B * fun()
{
cout << "B: " << endl;
return this;
}
};
void test(A & x)
{
x.fun();
}
int main()
{
A a;
B b;
test(a);
test(b);
return 0;
}
使用虚函数的一些限制
(1):只有类成员函数才能声明为虚函数,这是因为虚函数只适用于有继承关系的类对象中。
(2):静态成员函数不能说明为虚函数,因为静态成员函数不受限与某个对象,整个内存中只有一个,所以不会出现混淆的情况
(3):内联函数不可以被继承,因为内联函数是不能子啊运行中动态的确认其位置的。
(4):构造函数不可以被继承。
(5):析构函数可以被继承,而且通常声明为虚函数。
纯虚函数
(1):解释
虚函数是在基类中被声明为virtual,并在派生类中重新定义的成员函数,可实现成员函数的动态重载
纯虚函数的声明有着特殊的语法格式:virtual 返回值类型成员函数名(参数表)=0;
(2):必要性:
在很多情况下,基类本身生成对象是不合情理的。例如,动物作为一个基类可以派生出老虎、孔雀等子类,但动物本身生成对象明显不合常理。为了解决上述问题,引入了纯虚函数的概念,将函数定义为纯虚函数(方法:virtual ReturnType Function()= 0;),则编译器要求在派生类中必须予以重载以实现多态性。同时含有纯虚拟函数的类称为抽象类,它不能生成对象。
(3):抽象类的解释
包含纯虚函数的类称为抽象类。由于抽象类包含了没有定义的纯虚函数,所以不能定义抽象类的对象。
在C++中,抽象类只能用于被继承而不能直接创建对象的类(Abstract Class)。
#include<iostream>
#include<cmath>
using namespace std;
class A
{
public :
virtual void fun() = 0;
};
class B :public A
{
public :
virtual void fun()
{
cout << "B: " << endl;
}
};
int main()
{
B b;
b.fun();
return 0;
}