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~~~~~~~~~