C++将派生类赋值给基类(向上转型)
1.将派生类对象赋值给基类对象
#include <iostream>
using namespace std;//基类
class A{
public:A(int a);
public:void display();
public:int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){cout<<"Class A: m_a="<<m_a<<endl;
}//派生类
class B: public A{
public:B(int a, int b);
public:void display();
public:int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}int main(){A a(10);B b(66, 99);//赋值前a.display();b.display();cout<<"--------------"<<endl;//赋值后a = b;a.display();b.display();return 0;
}
运行结果:
Class A: m_a=10
Class B: m_a=66, m_b=99
'----------------------------
Class A: m_a=66
Class B: m_a=66, m_b=99
2.将派生类指针赋值给基类指针
#include <iostream>
using namespace std;//基类A
class A{
public:A(int a);
public:void display();
protected:int m_a;
};
A::A(int a): m_a(a){ }
void A::display(){cout<<"Class A: m_a="<<m_a<<endl;
}//中间派生类B
class B: public A{
public:B(int a, int b);
public:void display();
protected:int m_b;
};
B::B(int a, int b): A(a), m_b(b){ }
void B::display(){cout<<"Class B: m_a="<<m_a<<", m_b="<<m_b<<endl;
}//基类C
class C{
public:C(int c);
public:void display();
protected:int m_c;
};
C::C(int c): m_c(c){ }
void C::display(){cout<<"Class C: m_c="<<m_c<<endl;
}//最终派生类D
class D: public B, public C{
public:D(int a, int b, int c, int d);
public:void display();
private:int m_d;
};
D::D(int a, int b, int c, int d): B(a, b), C(c), m_d(d){ }
void D::display(){cout<<"Class D: m_a="<<m_a<<", m_b="<<m_b<<", m_c="<<m_c<<", m_d="<<m_d<<endl;
}int main(){A *pa = new A(1);B *pb = new B(2, 20);C *pc = new C(3);D *pd = new D(4, 40, 400, 4000);pa = pd;pa -> display();pb = pd;pb -> display();pc = pd;pc -> display();cout<<"-----------------------"<<endl;cout<<"pa="<<pa<<endl;cout<<"pb="<<pb<<endl;cout<<"pc="<<pc<<endl;cout<<"pd="<<pd<<endl;return 0;
}
运行结果:
Class A: m_a=4
Class B: m_a=4, m_b=40
Class C: m_c=400
'-----------------------
pa=0x9b17f8
pb=0x9b17f8
pc=0x9b1800
pd=0x9b17f8
3.virtual实现多态
#include <iostream>
using namespace std;//基类People
class People{
public:People(char *name, int age);void display();
protected:char *m_name;int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}//派生类Teacher
class Teacher: public People{
public:Teacher(char *name, int age, int salary);void display();
private:int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}int main(){People *p = new People("王志刚", 23);p -> display();p = new Teacher("赵宏佳", 45, 8200);p -> display();return 0;
}
#include <iostream>
using namespace std;//基类People
class People{
public:People(char *name, int age);virtual void display(); //声明为虚函数
protected:char *m_name;int m_age;
};
People::People(char *name, int age): m_name(name), m_age(age){}
void People::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是个无业游民。"<<endl;
}//派生类Teacher
class Teacher: public People{
public:Teacher(char *name, int age, int salary);virtual void display(); //声明为虚函数
private:int m_salary;
};
Teacher::Teacher(char *name, int age, int salary): People(name, age), m_salary(salary){}
void Teacher::display(){cout<<m_name<<"今年"<<m_age<<"岁了,是一名教师,每月有"<<m_salary<<"元的收入。"<<endl;
}int main(){People *p = new People("王志刚", 23);p -> display();p = new Teacher("赵宏佳", 45, 8200);p -> display();return 0;
}
4.多态例子:
#include <iostream>
using namespace std;//军队
class Troops{
public:virtual void fight(){ cout<<"Strike back!"<<endl; }
};//陆军
class Army: public Troops{
public:void fight(){ cout<<"--Army is fighting!"<<endl; }
};
//99A主战坦克
class _99A: public Army{
public:void fight(){ cout<<"----99A(Tank) is fighting!"<<endl; }
};
//武直10武装直升机
class WZ_10: public Army{
public:void fight(){ cout<<"----WZ-10(Helicopter) is fighting!"<<endl; }
};
//长剑10巡航导弹
class CJ_10: public Army{
public:void fight(){ cout<<"----CJ-10(Missile) is fighting!"<<endl; }
};//空军
class AirForce: public Troops{
public:void fight(){ cout<<"--AirForce is fighting!"<<endl; }
};
//J-20隐形歼击机
class J_20: public AirForce{
public:void fight(){ cout<<"----J-20(Fighter Plane) is fighting!"<<endl; }
};
//CH5无人机
class CH_5: public AirForce{
public:void fight(){ cout<<"----CH-5(UAV) is fighting!"<<endl; }
};
//轰6K轰炸机
class H_6K: public AirForce{
public:void fight(){ cout<<"----H-6K(Bomber) is fighting!"<<endl; }
};int main(){Troops *p = new Troops;p ->fight();//陆军p = new Army;p ->fight();p = new _99A;p -> fight();p = new WZ_10;p -> fight();p = new CJ_10;p -> fight();//空军p = new AirForce;p -> fight();p = new J_20;p -> fight();p = new CH_5;p -> fight();p = new H_6K;p -> fight();return 0;
}
5.dynamic_cast 关键字
dynamic_cast 用于在类的继承层次之间进行类型转换,它既允许向上转型(Upcasting),也允许向下转型(Downcasting)。向上转型是无条件的,不会进行任何检测,所以都能成功;向下转型的前提必须是安全的,要借助 RTTI 进行检测,所有只有一部分能成功。
5.1.向上转型(Upcasting)
向上转型时,只要待转换的两个类型之间存在继承关系,并且基类包含了虚函数(这些信息在编译期间就能确定),就一定能转换成功。因为向上转型始终是安全的,所以 dynamic_cast 不会进行任何运行期间的检查,这个时候的 dynamic_cast 和 static_cast 就没有什么区别了。
#include <iostream>
#include <iomanip>
using namespace std;class Base{
public:Base(int a = 0): m_a(a){ }int get_a() const{ return m_a; }virtual void func() const { }
protected:int m_a;
};class Derived: public Base{
public:Derived(int a = 0, int b = 0): Base(a), m_b(b){ }int get_b() const { return m_b; }
private:int m_b;
};int main(){//情况①Derived *pd1 = new Derived(35, 78);Base *pb1 = dynamic_cast<Derived*>(pd1);cout<<"pd1 = "<<pd1<<", pb1 = "<<pb1<<endl;cout<<pb1->get_a()<<endl; //OKcout<<pb1->get_b()<<endl; //NGcout<<pd1->get_b()<<endl; //OKpb1->func();return 0;
}
5.2.向下转型(Downcasting)
向下转型是有风险的,dynamic_cast 会借助 RTTI 信息进行检测,确定安全的才能转换成功,否则就转换失败。那么,哪些向下转型是安全地呢,哪些又是不安全的呢?下面我们通过一个例子来演示:
#include <iostream>
using namespace std;class A{
public:virtual void func() const { cout<<"Class A"<<endl; }
private:int m_a;
};class B: public A{
public:virtual void func() const { cout<<"Class B"<<endl; }
private:int m_b;
};class C: public B{
public:virtual void func() const { cout<<"Class C"<<endl; }
private:int m_c;
};class D: public C{
public:virtual void func() const { cout<<"Class D"<<endl; }
private:int m_d;
};int main(){A *pa = new A();B *pb;C *pc;//情况①pb = dynamic_cast<B*>(pa); //向下转型失败if(pb == NULL){cout<<"Downcasting failed: A* to B*"<<endl;}else{cout<<"Downcasting successfully: A* to B*"<<endl;pb -> func();}pc = dynamic_cast<C*>(pa); //向下转型失败if(pc == NULL){cout<<"Downcasting failed: A* to C*"<<endl;}else{cout<<"Downcasting successfully: A* to C*"<<endl;pc -> func();}cout<<"-------------------------"<<endl;//情况②pa = new D(); //向上转型都是允许的pb = dynamic_cast<B*>(pa); //向下转型成功if(pb == NULL){cout<<"Downcasting failed: A* to B*"<<endl;}else{cout<<"Downcasting successfully: A* to B*"<<endl;pb -> func();}pc = dynamic_cast<C*>(pa); //向下转型成功if(pc == NULL){cout<<"Downcasting failed: A* to C*"<<endl;}else{cout<<"Downcasting successfully: A* to C*"<<endl;pc -> func();}return 0;
}