多态性问题详解

一:父类指针和子类指针

class A
{
public:
       void fun()
       {
              cout << "调用了类A的void fun()函数" << endl;
       }      
};
class B:public A
{
public:
       void fun1()
       {
              cout << "调用了类B的void fun1()函数" << endl;
       }      
};
int main()
{      
       A *p = new B; //父类指针可以new一个子类对象
       //但是不可以通过父类指针调用子类的成员函数
       p->fun(); //可以
       //p->fun1();//不可以
       delete p;
}

说明:父类指针可以指向一个子类对象,但是,子类指针不可以指向一个父类对象。

虽然,父类指针指向一个子类对象,但是如果父类和子类如果有相同的同名,同参函数,但是,调用时调用的还是父类里的函数。例如:

class A
{
public:
       void fun()
       {
              cout << "调用了类A的void fun()函数" << endl;
       }      
};
class B:public A
{
public:
       void fun()
       {
              cout << "调用了类B的void fun()函数" << endl;
       }      
};
int main()
{      
       A *p = new B;
       p->fun(); //可以,调用的是cout << "调用了类A的void fun()函数" << endl;
       delete p;
}

思考?

如果,想通过定义一个指针就可以调用父类或子类的同名函数,有没有办法?
答:有,虚函数的引入正是为了解决这个问题。

二:虚函数

对于上面的问题,有办法。
但是,对于这个指针和函数都有要求。
指针类型必须是父类指针,而函数的声明必须要加virtual,即虚函数。

class A
{
public:
       virtual void fun() //类外定义时不加virtual
       {
              cout << "调用了类A的void fun()函数" << endl;
       }      
};
class B:public A
{
public:
       void fun() //子类的void fun()函数可以不加virtual
       {
              cout << "调用了类B的void fun()函数" << endl;
       }      
};
int main()
{      
       A *p = new B;//函数有了virtual的修饰后,new谁便调用那个函数
       p->fun(); //没加virtual之前,调用的函数以指针类型为准
       delete p;

       p = new A;
       p->fun();
       delete p;
}
c++11 final override的应用

final:用在虚函数上,且是在父类中使用。
作用:禁止该函数在子类中重写这个函数。

class A
{
public:
       virtual void fun() final   //类外定义时不加virtual
       {
              cout << "调用了类A的void fun()函数" << endl;
       }      
};
class B:public A
{
public:
       void fun() //错误
       {
              cout << "调用了类B的void fun()函数" << endl;
       }      
};

override:用在虚函数中,且是在子类中使用。含有覆盖的意思,既然是覆盖,那覆盖前就必须要有和即将覆盖时的相同函数。
作用:防止在子类中,写错虚函数形式(函数返回类型,形参个数)

class A
{
public:
       virtual void fun() //类外定义时不加virtual
       {
              cout << "调用了类A的void fun()函数" << endl;
       }      
};
class B:public A
{
public:
       void fun(int a) override//错误,因为父类中没有void fun(int a)函数
       {
              cout << "调用了类B的void fun()函数" << endl;
       }      
};


虚函数总结:实行的是动态绑定,即运行时才知道绑到那个函数去,不能只写函数声明,必须写函数定义。
虚函数用于指针才有意义,用于对象时意义不大。

三:多态性
答:多态性主要针对的是虚函数。

四:纯虚函数

定义:在基类中声明的虚函数,但它在基类中没有定义,且在所有的子类中该函数必须重写。

写法:在函数声明后加=0;

说明:一个类中有了纯虚函数后,那么该类就成了抽象类,即该类不能定义对象。
所有的实现方法是通过子类去实现的。

class A
{
public:
       virtual void fun() = 0; //纯虚函数
       /*{
              cout << "调用了类A的void fun()函数" << endl;
       }*/    
};
class B:public A
{
public:
       void fun()
       {
              cout << "调用了类B的void fun()函数" << endl;
       }      
};
int main()
{             
       A p;//错误,A是一个抽象类
}

五:虚析构

基类的析构函数一般写成虚析构函数

class A
{
public:
       A()
       {
              cout << "调用了A()" << endl;
       }
       ~A()
       {
              cout << "调用了~A()" << endl;
       }
       
};
class B:public A
{
public:
       B()
       {
              cout << "调用了B()" << endl;
       }
       ~B()
       {
              cout << "调用~B()"<<endl;
       }
              
};
int main()
{
       A *p = new B;
       delete p;//没有调用B的析构函数
}
结论:父类指针new一个子类对象,在delete时,不会调用子类的析构函数。

在这里插入图片描述
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38158479/article/details/106451045