我正在尝试使用显式向下广播从父实例调用子函数(感谢指出@Aconcagua)。作为C ++的初学者,我有这样的事情:
Road currentRoad = ...;
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(dateinMillis, isRightDirection);
Run Code Online (Sandbox Code Playgroud)
类SpeedDataRoad继承自Road:
class SpeedDataRoad : public Road{
double getSpeedProfileTime(long dateinMillis, bool isRightDirection) {
...
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了错误:
从“ Road”到“ SpeedDataRoad”的C样式转换没有匹配的转换
关于我在做什么错的任何建议将不胜感激。
需要明确的是,我试图用Java实现的内容将像这样编写并可以正常工作:
duration = ((SpeedDataRoad) currentRoad).getSpeedProfileTime(currentTime, isRightDirection);
Run Code Online (Sandbox Code Playgroud)
您遭受一种称为“对象切片”的影响:
SpeedDataRoad sdr;
Road currentRoad = sdr;
Run Code Online (Sandbox Code Playgroud)
在第二行,按值将sdr分配给,但是后者的类型不合适以容纳完整的对象。因此,所有多余的部分都被简单地切掉,剩下的只是一个纯粹的对象,只包含原始对象的一部分。currentRoadSpeedDataRoadSpeedDataRoadRoadRoadsdr
同时,由于只剩下一个纯Road对象,因此无法将其转换回SpeedDataRoad对象。现在缺少的部分应该从哪里来?
这与为什么不能将多态类型直接放入std::vector基类的容器(如)完全相同。
您需要的是指针(如果您希望能够重新分配)或引用(否则为首选):
SpeedDataRoad sdr;
Road& currentRoad = sdr;
// ^ (!)
// or:
Road* currentRoad = &sdr;
Run Code Online (Sandbox Code Playgroud)
现在您可以进行投射了。但是明显的低调有不良设计的味道。从一开始就采用多态方法可能会更好:
class Road
{
public:
virtual double getSpeedProfileTime(long, bool) = 0;
// ^ pure virtual
// alternatively, you can provide a default implementation
};
class SpeedDataRoad : public Road
{
public:
double getSpeedProfileTime(long, bool) override
{ /* ... */ }
};
Run Code Online (Sandbox Code Playgroud)
现在您可以简单地拥有:
SpeedDataRoad sdr;
Road& currentRoad = sdr;
double profile = currentRoad.getSpeedProfileTime(0, false);
Run Code Online (Sandbox Code Playgroud)
作为虚拟对象,无论我们拥有哪个子类,以及以哪种方式覆盖该函数,您都将始终获得该函数的正确变体...
旁注1:您可能更喜欢更现代的C ++强制转换,而不是旧的C样式强制转换,而是可以控制更细粒度的操作:
Road* someRoad = ...;
SpeedDataRoad* sdr = static_cast<SpeedDataRoad*>(someRoad);
SpeedDataRoad* sdr = dynamic_cast<SpeedDataRoad*>(someRoad);
Run Code Online (Sandbox Code Playgroud)
你会使用static_cast,如果你是100%肯定该对象仅可期望的类型。您可以避免在这种情况下根本无法提供任何服务的运行时测试(无论如何,您还是100%确定,记得吗?)。奇怪的是重复发生的模板模式是典型的情况。
如果不能确定类型,然后使用dynamic_cast它,它将进行一些运行时类型检查std::bad_cast,如果实际类型是,则返回一个空指针(如果用于指针)或抛出一个(如果用于引用)。不是期望的类型(或子类型)。当将不同的多态类型存储在向量中时,会出现这种情况(如指向基类的指针,请参见上文)。但是再次:完全需要转换可能暗示您的设计存在缺陷。
(为完整起见:还有const_cast和reinterpret_cast,但是您应该远离这些,除非/直到您真的非常了解自己的工作。)
旁注2:与Java的区别。
在Java中,我们在本机和引用类型之间进行隐式区分。本地的总是通过值传递,引用的类型总是通过引用传递–好吧,Java引用实际上比C ++引用更像C ++ 指针(可以是null,可以重新分配)。在Java中,这是隐式发生的,在C ++中,您需要明确说明(另一方面,对于任何类型,您都可以同时具有两种行为)。
Java(Java!)引用上的Java行为类似于C ++ dynamic_cast(在引用(即抛出null)上,类型不匹配时不会返回)。
最后(关于我的多态性建议),在Java中,所有函数都是隐式虚拟的,在C ++中,您必须再次明确(使用virtual关键字,请参见上文)。
| 归档时间: |
|
| 查看次数: |
141 次 |
| 最近记录: |