您的位置:首页 > 编程语言 > C语言/C++

理解多态

2016-03-22 13:18 295 查看
多态
多态即多种状态
多态又分为静态多态和动态多态,静多态即重载,动态多态即通过继承将基类的虚函数重写
虚函数
class B
{
public:
void show()//
{
cout << "B::show" << endl;
}
};
class D :public B
{
public:
void show()
{
cout << "D::show" << endl;
}
};
void fun(B *pb)//只有传入基类指针才能指向函数
{
pb->show();
}
int main()
{
D d;
B b;
fun(&d);
fun(&b);
getchar();
return 0;
}
输出结果:B::show()
B::show()
若在基类的同名函数前加virtual变为虚函数
输出结果:D::show()
B::show()
--->覆盖:子类重新定义了基类的虚函数并且他们的函数名参数列表和返回值均相同(协变除外)
多态:
用基类的指针指向基类的对象,调用虚方法(virtual)
1.派生类重写基类的虚方法实现多态,要求函数名、参数、返回值完全相同(协变除外)。
ps:协变即在基类的方法中返回基类的指针,子类返回子类的指针,即返回值不同
2.若在基类中是虚函数,则在子类中也是虚函数(保持虚函数特性)
3.只有类的成员才能定义为虚方法
4.静态成员函数(默认成员列表中无this)不能定义为virtual
5.在类外实现类的成员函数时,只能在类内声明时加virtual,在类外定义时不加virtual
6.构造函数不能定义为虚函数,operator=最好不要定义为虚函数
7.不要在构造函数和析构函数中调用虚函数
8.最好把基类的析构函数写为虚函数
class B
{
public:
B()
{
cout << "B()" << endl;
}
~B()
{
cout << "~B()" << endl;
}
};
class D :public B
{
public:
D()
{
cout << "D()" << endl;
}
~D()
{
cout << "~D()" << endl;
}
};
int main()
{
//D d;
B *pb = new D;
delete pb;
system( "pause");
return 0;
}
输出:B()
D()

~B()
不会调用子类的析构函数
子类调用析构函数时会自动调用基类的析构函数,故在基类的析构函数前加virtual时,则析构时先析构子类再析构基类

定义为virtual的函数的地址均依次保存在__vfptr的指向表内
class B
{
public:
virtual void show()//
{
}
};
class D :public B
{
public:
void show()
{
}
int _d;
};
int main()
{
cout << sizeof(D ) << endl;
getchar();
return 0;
}
输出:8
若去掉virtual,输出:4
typedef void (*PFUN)();
void PrintVT(int p)
{
PFUN pfun = NULL ;
int* ptr = (int *)p;
int i = 0;
while (ptr[i])
{
pfun = ( PFUN)ptr[i];
pfun();
i++;
}
}
class B
{
public:
virtual void fun1()
{
cout << "B::fun1" << endl;
}
virtual void fun2()
{
cout << "B::fun2" << endl;
}
private:
int _a;
};
class D :public B
{
public:
virtual void fun1()//覆盖
{
cout << "D::fun1" << endl;
}
virtual void fun3()
{
cout << "D::fun3" << endl;
}
virtual void fun4()
{
cout << "D::fun4" << endl;
}
private:
int _b;
};
int main()
{
D d;
PrintVT(*( int*)&d);
cout << "_________" << endl;
B b;
PrintVT(*( int*)&b);
getchar();
return 0;
}
输出:D::fun1//子类fun1覆盖了基类的fun1,虚函数里的地址覆盖
B::fun2
D::fun3
D::fun4
____________
B::fun1
B::fun2
多态即基类的虚函数被子类重写,其实是把属于子类的虚函数表里基类的虚函数地址改为子类的,这样,在创建指向基类的指针指向子类时即调用子类函数
void fun(B * pb)
{
pb->fun1();
}
fun(&d);//调用子类里的函数
纯虚函数
class Person
{
virtual void Display() = 0;
};
基类中有一个虚函数,在后面有“=0”的形式,且不实现,说明为虚函数,一般它的实现留给该基类的派生类。
带有纯虚函数的类称为抽象类或者接口类。抽象类不能实例化对象,若子类继承抽象类而没有实现虚函数定义,则此子类也是抽象类不能实例化对象,只有实现了纯虚函数才能实例化对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ 多态