虚函数和多态

一   虚函数:在类的成员函数前面加上virtual关键字,则这个成员函数称为虚函数

       注意:只有类成员函数加virtual才能称为虚函数,普通函数不可以

二   虚函数的重写:在子类定义了一个与父类完全相同的虚函数时,则称子类的这个函数重写(覆盖)了父类的这个虚函数

三   多态的两个条件:1.虚函数重写(覆盖 )    两个要求(1)虚函数   (2)函数全都相同(参数,函数名,返回值)

                                  2.父类的指针或引用调虚函数

                 注意:重写时子类的virtual可以不用写,默认继承了虚函数属性(但是父类的必须要写)

看如下代码分析执行结果  

四   一些结论规则及其讲解

1.派生类重写基类的虚函数实现多态,要求函数名,参数列表,返回值完全相同(协变除外)

   协变是什么呢,指返回值可以不同(分别为父,子类指针引用)

2.只有类的成员函数才可以定义为虚函数

3.静态成员函数不能定义为虚函数

4.如果在类外定义虚函数,只能在声明时加virtual,类外定义函数时不能加virtual

5.构造函数不能为虚函数

   原因:虚函数是对象创造出来由对象才调的,构造函数说明对象还在初始化,创建的一个阶段。因此不可以。

6.虽然可以将operator=定义为虚函数,但是最好不要将其定义为虚函数,因为使用时容易引起混淆。

    解释:成员函数里面子类operator=是一个合成版本,合成版本也就是说子类赋值时只赋值子类的,父类的不管

               去调用父类的去赋值,这时就有一个问题,你如果把它定义为虚函数,构成多态的行为,就可能导致一                  个死循环

        

7.不要在构造函数和析构函数里面调用虚函数,在构造函数和析构函数中对象是不完整的,可能会发生未定义的行   为。


      因为虚函数有可能调到子类,子类有可能没有初始化,有可能已经析构了,因此出错

class A
{
public:
	A(int x) 
	   :_pa(new int(10))
	{}
	A(const A& a)
	{
		a.f();//当拷贝构造子类对象时,子类的拷贝构造函数会调用父类的拷贝构造函数合成,
		//此时构成了多态又调用子类函数,而子类对象都没有初始化好,因此会出错
	}
	virtual void f()const
	{
		cout << *_pa << endl;
		cout << "A" << endl;
	}
protected:
	int* _pa;
};
class B:public A
{
public:
	B()
		:A(10)
		, _pb(new int(20))
	{}
	B(const B& b)
		:A(b)
	{
		f();
	}
	virtual void f()const
	{
		cout << *_pb << endl;
		cout << "B" << endl;
	}
protected:
	int* _pb;
};
int main()
{
	B b1;
	B b2(b1);
	system("pause");
	return 0;
}

8.最好把基类的析构函数定义为虚函数。(另外析构函数比较特殊,因为派生类的析构函数跟基类的析构函数名称不一样,但仍是构成覆盖,因为编译器在这里做了特殊处理)可以认为函数名是相同的

原因:

class A
{
public:
	A(int x=10) 
	   :_pa(new int(10))
	{}
	 ~A()
	{
		delete _pa;
		cout << "~A()" << endl;
	}
protected:
	int* _pa;
};
class B:public A
{
public:
	B()
		:A(10)
		, _pb(new int(20))
	{}
	 ~B()
	{
		delete _pb;
		cout << "~B()" << endl;
	}
protected:
	int* _pb;
};
int main()
{
	A* pa = new B;
	delete pa;
	system("pause");
	return 0;
}

四  纯虚函数

   在成员函数的形参后面加上=0,则成员函数为纯虚函数,包含纯虚函数的类叫做抽象类(也叫接口类),抽象类不能实例化出对象,纯虚函数在派生类中重新定义以后,派生类才能实例化出对象


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值