多态(主要是虚函数)

一 .多态的概念

多态的概念:通俗来说,就是多种形态,具体点就是去完成某个行为,当不同的对象去完成时会
产生出不同的状态。

例子:普通人(成人)买票全价,学生买票半价

代码:

//普通人
class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "全价" << endl;
	}
};

class Student : public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "半价" << endl;
	}
};

void func(Person& p)//或者Person* p
{
	p.BuyTicket();
	//指针:p->BuyTicket();
}
int main()
{
	Person p;
	Student s;

	func(p);
	func(s);

//打印
//全价
//半价
	return 0;
}

二 . 解释上述代码

1.虚函数

虚函数:即被virtual修饰的类成员函数称为虚函数。
(虚函数只在类里才是虚函数,非类成员函数不能加virtual)

	virtual void BuyTicket()
	{
		cout << "全价" << endl;
	}

2.虚函数重写

虚函数的重写(覆盖):派生类中有一个跟基类完全相同的虚函数(即派生类虚函数与基类虚函数的
返回值类型、函数名字、参数列表完全相同),称子类的虚函数重写了基类的虚函数。

 (另外基类的virtual必须写,否则不构成多态;子类的virtual可以不用写)

3.多态的条件


另一种多态代码:

class Person
{
public:
	virtual void BuyTicket()
	{
		cout << "全价" << endl;
	}
};

class Student : public Person
{
public:
	virtual void BuyTicket()
	{
		cout << "半价" << endl;
	}
};

int main()
{
	Person p;
	Student s;

	Person* ptr = &p;
	ptr->BuyTicket();//全价
	
	ptr = &s;
	ptr->BuyTicket();//半价
	return 0;
}

4.虚函数重写的例外

(1)协变:返回值可以不同,但是必须是父子类的指针或引用
 

class Person
{
public:
	virtual Person* BuyTicket()
	{
		cout << "全价" << endl;
        return this;
	}
};

class Student : public Person
{
public:
	virtual Student BuyTicket()
	{
		cout << "半价" << endl;
        return this;
	}
};

(2)析构函数名不同(重点)

class Person {
public:
	virtual ~Person() { cout << "~Person()" << endl; }
};
class Student : public Person {
public:
	virtual ~Student() { cout << "~Student()" << endl; }
};

int main()
{
	Person* p1 = new Person;
	Person* p2 = new Student;
	delete p1;
	delete p2;
//如果不是虚函数重写,p1,p2都只会调用~Person(),会出现内存泄漏的问题
	return 0;
}

 总结:

普通调用(不构成多态条件都是普通调用):调用函数的类型是谁,就调用此类型对应的函数是。

多态调用:调用指针或引用指向的对象。指向父类则调用父类的函数,指向子类则调用子类的函数。

5.来个题目增加对多态的认识

class A
{
public:
	virtual void func(int val = 1) 
	{
		std::cout << "A->" << val << std::endl; 
	}

    virtual void test() { func(); }
};
class B : public A
{
public:

	void func(int val = 0) 
	{
		std::cout << "B->" << val << std::endl; 
	}
};

int main(int argc, char* argv[])
{
	B* p = new B;
	p->test();
	return 0;
}

这段代码打印什么?

解释和结果:

 

三 . 重载、覆盖(重写)、隐藏(重定义)的对比
 

四 . 抽象类 

在虚函数的后面写上 =0 ,则这个函数为纯虚函数。包含纯虚函数的类叫做抽象类(也叫接口
类),抽象类不能实例化出对象。派生类继承后也不能实例化出对象,只有重写纯虚函数,派生
类才能实例化出对象。纯虚函数规范了派生类必须重写,另外纯虚函数更体现出了接口继承。

class Car
{
public:
	virtual void Drive() = 0;
};
class Benz :public Car
{
public:
	virtual void Drive()
	{
		cout << "Benz-舒适" << endl;
	}
};
class BMW :public Car
{
public:
	virtual void Drive()
	{
		cout << "BMW-操控" << endl;
	}
};
void Test()
{
	Car* pBenz = new Benz;
	pBenz->Drive(); //Benz-舒适
	Car* pBMW = new BMW;
	pBMW->Drive();  //BMW-操控
}
int main()
{
	Test();
	return 0;
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值