C++程序设计POJ》《WEEK6 多态与虚函数》

Posted focus-z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++程序设计POJ》《WEEK6 多态与虚函数》相关的知识,希望对你有一定的参考价值。

问题: 虚函数都是同名 同参数表的吗? 

虚函数和普通成员函数的区别

虚函数可以多态,其他不行

在构造函数和析构函数中调用 虚函数 不是多态

派生类还没有初始化好

MyCompare()

qsort 怎么表示排序关系

虚函数表地址!!

虚函数
?
在类的定义中,前面有 virtual 关键字的成员
函数就是虚函数。
class base

virtual   int get() ;

int base::get()


virtual 关键字只用在类定义里的函数声明中
写函数体时不用。
多态的表现形式一

?
派生类的指针可以赋给基类指针
?
通过基类指针调用基类和派生类中的同名 虚函数

1 )若该指针指向一个基类的对象,那么被调用
基类的 虚函数

2 )若该指针指向一个派生类的对象,那么被调
用的是派生类的 虚函数
这种机制就叫做“
多态 ”。

class CBase 
public:
virtual  void SomeVirtualFunction()  
;
class CDerived:public CBase 
public :
virtual  void SomeVirtualFunction()  
;
int main() 
CDerived ODerived;
CBase * p = & ODerived; 
p-> SomeVirtualFunction(); // 调用哪个虚函数取决于 p 指向哪种类型的对象  调用CDerived类的虚函数
return 0;

 

多态的表现形式二
?
派生类的对象可以赋给基类引用
?
通过基类引用调用基类和派生类中的同名 虚函数 时

1 )若该引用引用的是一个基类的对象,那么被
调用是基类的 虚函数

2 )若该引用引用的是一个派生类的对象,那么
被调用的是派生类的 虚函数 。
这种机制也叫做“
多态 ”。

class CBase 
public:
virtual
void SomeVirtualFunction()  
;
class CDerived:public CBase 
public :
virtual
void SomeVirtualFunction()  
;
int main() 
CDerived ODerived;
CBase & r = ODerived;
r.SomeVirtualFunction(); //调用哪个虚函数取决于 r 引用哪种类型的对象
return 0;

多态的作用

 

在面向对象的程序设计中使用多态,能够增强
程序的 可扩充性 ,即程序需要修改或增加功能
的时候,需要改动和增加的代码较少。

 

/*
几何形体处理程序
Sample Input:
3
R 3 5
C 9
T 3 4 5
Sample Output
Triangle:6
Rectangle:15
Circle:254.34
39
*/
#include<iostream>
#include<stdlib.h>
#include<math.h>

using namespace std;
class CShape

public:
    virtual double Area() = 0; // 纯虚函数
    virtual void PrintInfo() = 0;
;

class CRectangle :public CShape

public:
    int w, h;
    virtual double Area();
    virtual void PrintInfo();
;
class CCircle :public CShape

public:
    int r;
    virtual double Area();
    virtual void PrintInfo();

;
class CTriangle :public CShape

public:
    int a, b, c;
    virtual double Area();
    virtual void PrintInfo();
;
double CRectangle::Area()

    return w*h;

void CRectangle::PrintInfo()

    cout << "rectanlgle:" << Area() << endl;


double CCircle::Area()

    return 3.14*r*r;

void CCircle::PrintInfo()

    cout << "circle:" << Area() << endl;

double CTriangle::Area()

    double p = (a + b + c) / 2.0;
    return sqrt(p*(p - a)*(p - b)*(p - c));

void CTriangle::PrintInfo()

    cout << "triangle:" << Area() << endl;


CShape * pShapes[100]; // 基类 指针数组
int MyCompare(const void *s1, const void *s2);

int MyCompare(const void* s1, const void *s2)

    double a1, a2;
    CShape** p1; // s1,s2 是 void * ,不可写 ““* s1 ”来取得 s1 指向的内容
    CShape** p2;
    p1 = (CShape**)s1;//s1,s2 指向 pShapes 数组中的元素,数组元素的类型是 CShape *
    p2 = (CShape**)s2;// 故 p1,p2 都是指向指针的指针,类型为 CShape **
    a1 = (*p1)->Area();// * p1 的类型是 Cshape * , 是基类指针,故此句为多态
    a2 = (*p2)->Area();
    if (a1 < a2)
        return -1;
    else if (a2 < a1)
        return 1;
    else
        return 0;

int main()

    int i, n;
    CRectangle *pr;
    CCircle *pc;
    CTriangle *pt;
    cin >> n;
    for (i = 0; i < n; i++)
    
        char c;
        cin >> c;
        switch (c)
        
        case R:
            pr = new CRectangle();
            cin >> pr->w >> pr->h;
            pShapes[i] = pr; // 派生类指针 赋给 基类
            break;
        case C:
            pc = new CCircle;
            cin >> pc->r;
            pShapes[i] = pc;
            break;
        case T:
            pt = new CTriangle();
            cin >> pt->a >> pt->b >> pt->c;
            pShapes[i] = pt;
            break;

        
    

    qsort(pShapes, n, sizeof(CShape*), MyCompare);
    for (i = 0; i < n; i++)
        pShapes[i]->PrintInfo();
    while (1);
    return 0;

用基类指针数组存放指向各种派生类对象的指
针,然后遍历该数组,就能对各个派生类对象
做各种操作,是很常用的做法

构造函数和析构函数中调用虚函数

在构造函数和析构函数中调用虚函数,不是多态。编
译时即可确定,调用的函数是 自己的类或基类 中定义
的函数,不会等到运行时才决定调用自己的还是派生
类的函数。

 

派生类中和基类中虚函数同名同参数表的函数,不加
virtual 也自动成为虚函数

class myclass
public:
virtual void hello()cout<<"hello from myclass"<<endl; ;
virtual void bye()cout<<"bye from myclass"<<endl;
;
class son:public myclass

void hello() cout<<"hello from son"<<endl;;
son() hello();
~son()bye(); ;
class grandson:public son

void hello()cout<<"hello from grandson"<<endl;;
void bye()  cout << "bye from grandson"<<endl;
grandson()cout<<"constructing grandson"<<endl;;
~grandson()cout<<"destructing grandson"<<endl;;
;
int main()
grandson gson;
son *pson;
pson=&gson;
pson->hello(); 多态
return 0;

/*
结果:
hello from son
constructing grandson
hello from grandson
destructing grandson
bye from myclass

*/

虚函数的访问权限

class Base 
private:
virtual void fun2()  cout << "Base::fun2()" << endl; 
;
class Derived:public Base 
public:
virtual void fun2()  cout << "Derived:fun2()" << endl; 
;
Derived d;
Base * pBase = & d;
pBase-> fun2(); // 编译出错

编译出错是因为 fun2() 是 Base 的私有成员。即使运行到此时实际上调用的应该是
Derived 的公有成员 fun2() 也不行,因为语法检查是不考虑运行结果的。
?
如果 将 Base 中的 private 换成 public, 即使 Derived 中的 fun2() 是 private 的,编译依然能通
过,也能正确调用 Derived::fun2() 。

#include<iostream>
using namespace std;
class Base

public:
    virtual void fun2()
    
        cout << "base::fun2()" << endl;
    
;
class Derived :public Base

private:
    virtual void fun2()
    
        cout << "Derived:fun2()" << endl;
    
;

int main()

    Derived d;
    Base * pBase = &d;
    pBase->fun2(); // 神奇了,private也能访问!!!
    while (1);
    return 0;

 

以上是关于C++程序设计POJ》《WEEK6 多态与虚函数》的主要内容,如果未能解决你的问题,请参考以下文章

C++程序设计POJ》《WEEK6 多态与虚函数》《编程填空》

C++之多态性与虚函数

C++多态性与虚函数

C++的探索路14多态与虚函数之基础篇

C++的探索路15多态与虚函数之高级篇

C++的探索路16多态与虚函数之练习篇