C++多态(上):

本文深入探讨了C++中的多态性,包括静态和动态多态,重点讲解了虚函数的作用和实现方式。通过实例解析了虚函数重写、析构函数的特殊性,以及C++11引入的`final`和`override`关键字。同时,文中还澄清了重写、隐藏和重定义等概念的区别。
摘要由CSDN通过智能技术生成

--------------"感谢在那每一次跌倒了以后,又重新来过"


(1)多态的概念以及定义:

①定义:

多态:俗称多种形态。每个具体的行为,去做同一件事情,产生不同的状态。

对语言来说,也就是灵活调用。

多态有两个种类;

1.静态的多态,也就是函数重载;(编译时,依靠函数名修饰规则)

2.动态的多态(运行时,找到父类、子类虚函数),构成条件如下......

(2)多态实现:

构成条件:

1. 必须通过基类的指针或者引用调用虚函数

2. 被调用的函数必须是虚函数,且派生类必须对基类的虚函数进行重写

父类指针、引用指向父类对象 调用父类虚函数

父类指针、引用指向子类对象 调用子类虚函数         ----->指向哪个对象的调用哪个

这里就有个问题---->什么是虚函数?


(3)虚函数:

即被virtual修饰的函数(这和虚继承的关键字一样,但意义不一样!!!)

class Person
{
public:
    //虚函数
	virtual void PrintTicket()
	{
		cout << "买票---全价" << endl;
	}
};

什么又叫做虚函数重写呢?

class Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---全价" << endl;
	}
};

class Student:public Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---半价" << endl;

	}
};

class Soilder:public Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---优先" << endl;
	}
};

也就是,在派生类中有一个跟基类完全相同的虚函数。

他们在返回类型函数名参数列表 完全相同。

class Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---全价" << endl;
	}
};

//虚函数重写
class Student :public Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---半价" << endl;

	}
};

class Soilder :public Person
{
public:
	virtual void PrintTicket()
	{
		cout << "买票---优先" << endl;
	}
};

//父类指针\引用     调用
void Func(Person& p)
{
	p.PrintTicket();
}

void Func(Person* p)
{
	p->PrintTicket();
}


虚函数重写例外(例外 构成重写条件)

1.协变(基类和派生类 返回值可以不同)

我们来看看下面代码:

class A{};

class B :public A{};

class ForA 
{
public:
	virtual A* Print()
	{
		cout << "ForA()" << endl;
		return new A;
	}
};

class ForB:public ForA
{
public:
	virtual B* Print()
	{
		cout << "ForB()" << endl;
		return new B;
	}
};

A是基类,B是子类。他们分别作为另外一组继承关系的返回值。 此时他们构成协变。

2.析构函数的重写:

class A 
{
public:
	~A()
	{
		cout << "~A()" << endl;
	}
};

class B:public A
{
public:
	~B()
	{
		cout << "~B()" << endl;
	}
};

我们分别对A、B生成的对象进行析构 

 这和我们想要的不太一样。因为我们new 出来的B类并没有去调用析构 反而调用了两次A析构。

我们知道,编译器会把基类、派生类的析构函数统一改成,destructor(),从而隐藏,但在这里也就误打误撞构成 也就完成了重写。

class A 
{
public:
     //基类 带上虚函数 方便 子类重写
	  virtual ~A()
	{
		cout << "~A()" << endl;
	}
};

class B:public A
{
public:
	virtual ~B()
	{
		cout << "~B()" << endl;
	}
};

从而,让虚函数进行重写了。a,b才能分别找到自己对应的 析构函数进行 清理!实现多态。  

3.基类构成虚函数后,子类只需要重写

这个也算C++设计的一个坑。搞得重写不太严谨。

这样的理由在于,析构时,让父类构成虚函数(virtual)后,子类也就继承virtual的属性,让子类也对函数进行了重写。

class A 
{
public:
    //这只让 A 构成虚函数
	  virtual ~A()
	{
		cout << "~A()" << endl;
	}
};

class B:public A
{
public:
   //继承 虚函数的特性
	 ~B()
	{
		cout << "~B()" << endl;
	}
};


 (4)C++11引入新关键字

final:修饰的虚函数不能被继承

class Car
{
public:
	virtual void Drive() final{}
};

class BMW :public Car
{
public:
	virtual void Drive();
};

2.override:检查派生类虚函数是否重写了基类某个虚函数,如果没有重写编译报错

class Car
{
public:
	virtual void Drive() {}
};

class BMW :public Car
{
public:
	virtual void Drive() override
	{}
};

(5)概念对比与区别

学到现在,一定对有些概念记得混淆。重写、隐藏、重定义.......

 


 多态上篇也就告一段落,感谢你的阅读。

祝你好运~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值