lv19 多态 4

时间:2024-03-01 16:08:04

1 虚函数

虚函数( 基类指针可指向派生类对象, 动态联编)

先看示例,不加virtual,不认对象认指针。

#include <iostream>

using namespace std;

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

class AX:public A{
public:
	void show()
	{
		cout<<"BBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{

/*
	A a;
    a.show();//AAAAAAAAAAAAA

	AX b;
	b.show();//BBBBBBBBBBBBB
*/
	
	AX a;//定义派生类
	AX *q = &a; //认函数
	A  *p = &a;
	q->show();  //BBBBBBBBBBBBB
	p->show();  //AAAAAAAAAAAAA

}

加上virtul,通过指针找到对象,对象类型是什么调什么函数。动态链接的方式。

#include <iostream>

using namespace std;

class A{
public:
	A(){ }
    ~A(){ }
	
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	void show()
	{
		cout<<"BBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{

/*
	A a;
    a.show();//AAAAAAAAAAAAA

	AX b;
	b.show();//BBBBBBBBBBBBB
*/
	
	AX a;//定义派生类
	AX *q = &a; //认函数
	A  *p = &a;
	q->show();  //BBBBBBBBBBBBB
	p->show();  //BBBBBBBBBBBBB

}

2 多态应用

设计一个函数能求多个“图形”总周长。

纯虚类用法

#include <iostream>

using namespace std;

class shape{
public:
	virtual double getC(void) = 0;    //纯虚函数的声明,表示在派生类中必须实现该函数,否则编译器不通过。
//	{                                 //虚函数可以不要求派生类必须实现

//	}
};

class Cir:public shape{
public:
	Cir(double ri):r(ri) { }
	double getC(void)
	{
		return 2*3.14*r;	
	}
private:
	int r;
};

class Tri:public shape{
public:
	Tri(double a, double b, double c):e1(a),e2(b),e3(c){ }

	double getC(void)
	{
		return e1+e2+e3;	
	}
private:
	double e1;
	double e2;
	double e3;
};

class Rec: public shape{
public:
	Rec(double e)
	{
		this->e = e;
	}
	double getC(void)
	{
		return 4*e;	
	}

private:
	double e;
};

double countC(shape *arr[], int n)
{
	double sum = 0;
	for(int i=0; i<n; i++)
	{
		sum += arr[i]->getC();
	}
	
	return sum;
}

int main()
{
	//shape x;  //如果是纯虚函数的声明会编译不通过

	Cir c(1);
	Rec r(3);
	Cir c1(2);
	Tri t(3,3,3);

	shape *arr[] = {&c, &r, &c1, &t};

	cout << "total C: "<<countC(arr, 4) << endl;
}

3 虚析构函数

现象

#include <iostream>

using namespace std;

class A{
public:
	A(){ }
	~A(){ cout<<"A~~~~~~~~~"<<endl; }
	//virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }  //加virtual 也一样调用3次
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{
	AX a;   //派生类构造的时候调用了1次基类构造函数,所以析构的时候有2次
	A b;
}

//析构函数调用了3次

A~~~~~~~~~   //a
AX~~~~~~~~~  //a
A~~~~~~~~~   //b
#include <iostream>

using namespace std;

class A{
public:
	A(){ }	
    virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }  //加virtual 也一样调用3次
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{
	AX a;   //派生类构造的时候调用了1次基类构造函数,所以析构的时候有2次
	A b;
}

//析构函数调用了3次

A~~~~~~~~~   //a
AX~~~~~~~~~  //a
A~~~~~~~~~   //b

#include <iostream>

using namespace std;

class A{
public:
	A(){ }
	virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }
	
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{
	AX *p = new AX;
	delete p;
}

//
AX~~~~~~~~~
A~~~~~~~~~
#include <iostream>

using namespace std;

class A{
public:
	A(){ }
	virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }
	
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{
	AX *p = new AX;
	delete p;    //
}
//
AX~~~~~~~~~
A~~~~~~~~~

不安全的情况 

#include <iostream>

using namespace std;

class A{
public:
	A(){ }
	~A(){ cout<<"A~~~~~~~~~"<<endl; }
	
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{

	A *p = new AX;
	delete p;   //析构不完整

}

//
A~~~~~~~~~

//virtual 用在析构函数上安全一点,防止内存泄漏
#include <iostream>

using namespace std;

class A{
public:
	A(){ }
	virtual ~A(){ cout<<"A~~~~~~~~~"<<endl; }
	
	virtual void show()
	{
		cout<<"AAAAAAAAAAAAA"<<endl;
	}
	
};

class AX:public A{
public:
	~AX(){ cout<<"AX~~~~~~~~~"<<endl; }
	void show()
	{
		cout<<"BBBBBBBBBBBBBB"<<endl;
	}
	
};

int main()
{

	A *p = new AX;
	delete p;   

}

//
AX~~~~~~~~~
A~~~~~~~~~