C++ 多态小示例

#include <string.h>
#include <iostream>

using namespace std;

class Employee{
    protected :
        char name[20];
    public:
        Employee(const char *str){
            strcpy(this->name,str);            
        }
        
        virtual void display(){
            cout<<"Employee::display()"<<endl;
        }
        
        void fun_nonvirtual(){
            cout<<"Employee::fun_nonvirtual()"<<endl;
        }
};

class Manager:public Employee{
    private:
        int deptId;
    public:
        Manager(const char *str):Employee(str){
            this->deptId=0;
        }
        
        void display(){
            cout<<"Manager::display(), "<<"name = " <<name<<endl;
        }
        
        void fun_nonvirtual(){
            cout<<"Manager::fun_nonvirtual()"<<endl;
        }
        
        void xxx(){
            cout<<"Manager::xxx(), "<<this->deptId<<endl;
        }
};

int main(){
    
    cout<<sizeof(Manager)<<endl;  //sizeof(Manager) = 28 , 20+4+4(name+deptId+vptr) 
        
    Employee *pe1;
    Manager m1("张三");
    pe1=&m1;
    pe1->display(); //Manager::display() 多态(指针或引用+虚函数) 
    pe1->fun_nonvirtual(); //Employee::fun_nonvirtual() 指针pe1声明类型为Employee 
    
    Employee e2=m1; //拷贝构造函数负责将对象e2的vptr指向类型Employee的vtable 
    e2.display();   //vtable之display指向Employee::display() 
    
    Employee e1("张九");
    Manager *pm;
    pm=(Manager*)(&e1); //需要强制类型转化,否则编译不通过 
    pm->xxx();          //打印出deptId为乱码 
    
    return 0;
}

注意事项

1、虚函数派生下去仍为虚函数,而且可以省略virtual关键字;

2、派生类会继承基类的虚函数表,当我们在派生类中改写虚函数时,虚函数表就受到影响:表中元素所指的函数地址将不再是基类的函数地址,而是派生类的函数地址;

3、以单一指令调用不同函数,就是多态;

4、一个“基类之指针”指向“派生类之对象”,那么经由该指针你只能调用基类所定义的函数(虚函数除外);

5、以一个“派生类之指针”指向一个“基类之对象”,必须先做明显的转型操作(explicit cast),这种做法存在危险;  

 

posted @ 2015-10-18 20:21  chenyizh  阅读(231)  评论(0)    收藏  举报