多态:
1、多态形成的条件:
1、必须有类的继承关系;
2、继承关系中用同名虚函数;
3、必须有基类指针;
2、多态体现在,基类指针有很多的表现方式;例如:
class A{};
class B:public A{};
int main()
{
A *ptr=new B;
}
这里我们定义两个类,基类A和派生类B,在主函数中,定义了一个基类指针ptr;指向了B这个派生类。那么这个指针就可以访问 从A继承的pubic函数。
这里又涉及到一个遮蔽的问题;
例如:
class A{
public:
virtual void say()
};
class B:public A{
public:
virtual void say()
void print()
};
int main()
{
A *ptr=new B;
ptr->say();
}
这边 ptr->say调用的函数,就是B中遮蔽了基类A的函数SAY,如果说B中没有SAY这个函数那么,系统会往上层寻找,一直到找到这个函数,比如这里的程序,如果B没有,那么就会调用A里面的SAY;如果没有的话那么就报错。
此外,基类指针是没办法访问,它指向的类的本身的函数的,例如上面的函数,ptr->print()这个函数是没有办法访问的,会报错:class A中没有这个函数。
#include <iostream>
using namespace std;
class A{
protected:
char *name;
char *sex;
public:
A(char*,char*);
void virtual say();
void pr();
};
A::A(char *n,char *s):name(n),sex(s){}
void A::pr()
{
cout<<"i am a"<<endl;
}
void A::say()
{
cout<<name<<" 性别是"<<sex<<endl;
}
class B:public A{
protected:
float score;
public:
B(char *,char *,float);
void virtual say();
void print();
};
B::B(char *n,char *s,float sc ):A(n,s),score(sc){}
void B::print()
{
cout<<name<<" "<<sex<<"成绩是"<<score<<endl;
}
int main()
{
A *pt=new A("xiaoming","male");
pt->say();
pt=new B("xiaoli","female",89.5);
pt->print();
pt->say();
pt->pr();
return 0;
}
在这个函数中,定义了一个基类A的指针pt 初始化了,然后调用的SAY这个函数,再把这个基类指针给了 B类,调用B类的函数say(),在这里调用Print是错误的,因为class A中没这个虚函数,pt指向了B 调用了pr系统在B中没有找到这个函数,去基类A中寻找找到了,所以调用A中函数Pr();就输出了 i am a这个句子。
虚函数和多态的意义在与,可以使一个指针进行多样化操作。使一个指针有了很多种变化。
总结:有继承关系的两个类中,两个函数完全相同,在基类中定义成虚函数,基类指针对不同的类进行指向,然后就可以访问内容不同同名虚函数。
**函数需要是无论返回值,形参,函数名都一样的两个函数。
2、析构函数需要改为虚函数吗?
直接看代码:#include <iostream>
using namespace std;
class A{
private:
char *m_name;
public:
A();
virtual ~A();
};
A::A()
{
m_name=new char [20];
cout<<"A 1"<<endl;
}
A::~A()
{
delete [] m_name;
cout<<"A 2"<<endl;
}
class B:public A
{
private:
char *id;
public:
B();
~B();
};
B::B()
{
id =new char [20];
cout<<"B 1"<<endl;
}
int main()
{
A *k=new B;
delete k;
}
在这个函数中,如果我们不把析构函数 设置成虚析构的话,那么运行结果是,A构造,B构造,A析构。B并没有析构,我们在构造函数中请求了20个字节的空间在堆上,如果不析构那么长时间的话就会出现内存泄露问题。所以我们需要在A的析构函数前面加上 virtual 虚函数的修饰,这样B类就会被析构了。
4、纯虚函数
纯虚函数是指,在基类中定义了函数,但是在函数后面加了 “=0”,这样函数就变成了纯虚函数,例如:
class A{
public:
int area()=0;
};
这里的area函数就是一个纯虚函数
纯虚函数在使用是需要注意,需要在派生类中,对所有的纯虚函数进行申明定义后才能,才能定义对象。