前言
在C++中,类型转换是常见的编程操作。上下行转换是类型转换的重要概念,其主要内容是关于在C++中两个有继承关系的类的相互转换。
上行转换
上行转换是指将派生类的对象转换为基类的对象。这是自动且安全的,因为派生类对象包含所有基类的信息。
代码示例
class Parent
{
public:
int getValue()
{
return i;
}
private:
int i = 1;
};
class Child : public Parent
{
public:
int getValue()
{
return d;
}
private:
int d = 2;
};
int main()
{
Child c;
cout << c.getValue() << endl;
Parent* p = &c;
cout<<p->getValue()<<endl;
return 0;
}
输出结果
2
1
在该段代码中,Child
重写了父类Parent
的getValue
函数,使其获取的变量值从i变为自身独有变量d;所以在没有上行转换时,类Child
实例对象c调用的是类Child
内的getValue
函数;而在进行了上行转换后,对象c调用的是类Parent内的getValue
函数
下行转换
下行转换是指将基类的对象转换为派生类的对象。这通常不是自动的,并且需要显式地进行类型转换。在C++中,可以使用 dynamic_cast
来尝试下行转换,它会检查转换是否安全。如果转换失败,则 dynamic_cast
返回一个空指针或对非指针类型抛出异常。
代码示例
class Parent
{
public:
virtual int getValue()
{
cout << "下行转换::父类" << endl;
return i;
}
private:
int i = 1;
};
class Child : public Parent
{
public:
int getValue() override
{
cout << "下行转换::子类" << endl;
return d;
}
void setValue(int value)
{
d = value;
}
private:
int d = 2;
};
int main()
{
Parent* p = new Parent();
p->getValue();
Child* c = dynamic_cast<Child*>(p);
c->getValue();
return 0;
}
输出结果
下行转换::父类
在代码示例中,我们实例一个父类对象,然后用dynamic_cast<Child*>()
将其赋值给一个子类Child
指针 。最后执行getvalue
函数,打印信息到终端。从输出结果来看, c->getValue();
执行存在问题,没有打印相关信息。
结论
- 上行转换是安全的
- 下行转换时不安全的
分析
在系统中,我们的代码存储在内存中。系统执行代码,也是需要找到代码的地址。在下行转换后,对象无法找到子类的相关函数,所以执行出现问题;
通俗理解:
如果将父类比作集装箱,继承父类的子类比作一辆载着集装箱的卡车;
那么上行转换就是:存在一辆载着集装箱的卡车,我们从看整体(车和集装箱)变为 仅看集装箱,虽然我们的视角固定在集装箱上,但是车也是存在的;
相对而言,下行转换就是:存在一个集装箱,我们的视角从仅看集装箱 改变为看整体,但是这个整体只有集装箱,没有车。所以我们看不到车;