在 c++ 中向下抛弃疑惑
Downcasting wondering in c++
我有下一个代码
class Shape
{
public:
virtual Shape* create() { return new Shape; }
virtual void print() { cout << "Shape" << endl; }
virtual ~Shape() {}
};
class Circle : public Shape
{
public:
virtual Circle* create() { return new Circle; }
virtual void print() { cout << "Circle" << endl; }
};
void foo ()
{
Shape* sp = new Circle;
Circle* cp = sp->create();
cp->print();
delete sp;
delete cp;
}
代码未编译,因为形状不是圆(向下转换错误(。
我有点困惑。create(( 不是动态绑定?行
Circle* cp = sp->create();
不应该返回循环*?
这是因为那条线
Circle* cp = sp->create();
由编译器在编译时计算。在编译时,它只知道sp
是指向Shape
的指针,因此在编译时使用Shape::create()
的签名。它无法知道指针指向什么,因为它是在运行时分配和设置的。要绕过它,请使用dynamic_cast
.
Circle* cp = dynamic_cast<Circle*>(sp->create());
向下投射不是隐式的。既然你知道自己在做什么(即sp
实际上是一个circle
(,使用dynamic_Cast
Circle* cp = dynamic_cast<Circle*>(sp->create());
您可以在静态类型为Shape
的实例上调用create()
。因此,函数签名是Shape* create()
。事实上,在 vtable 查找之后,调用的实际函数是Circle::create()
的,但是将Circle
实例存储为Shape
引用的目的是隐藏具体类型、其成员函数以及可能的协变返回类型。
要通过Circle::create()
获取Circle
对象,您可以
Circle *c1 = new Circle; // Static type info (Circle) is preserved
Circle *c2 = c1->create(); // Ok, the covariant return type is Circle*
或
Shape *s1 = new Circle; // Everything Circle-related lost on the lhs
Circle *c1 = dynamic_cast<Circle*>(s1->create()); // Manually restore with RTTI
尽管后者暗示出了问题(为什么需要从基类接口创建子类实例而不隐藏其具体类型?
作为旁注,您还可以考虑更改函数签名,使其返回std::unique_ptr<Shape>
或std::unique_ptr<Circle>
,这对于返回多态类实例的工厂函数来说是很好的做法。
将形状指针投射到圆圈。
Circle* cp = (Circle* sp)->create();
相关文章:
- 在 c++ 中向下抛弃疑惑
- Static_cast 对于康斯特来说,会抛弃预选赛
- C++如何抛弃函数的虚拟性并调用基本函数,而不是覆盖
- 抛弃 *这会导致未定义的行为吗?
- C++17 标准 - 抛弃静态常量
- 虚函数疑惑
- 在模板中强制转换为引用似乎会抛弃恒定性
- 从指针或引用中抛弃常量/易失性
- 抛弃灾难的例外 - 缺点是什么
- 抛弃康斯特,就是这种定义明确的行为
- reinterpret_cast抛弃了预选赛
- 康斯特是谎言吗?(因为康斯特可以被抛弃)
- 这是抛弃康斯特吗?
- 当函数引用对象(并访问非常量方法)时,如何抛弃常量?
- 这个移动构造函数的实现是否抛弃了移动语义?
- 你能从易失性函数中抛弃成员上的易失性吗>
- 从"this"中抛弃恒常性,然后更改成员值是否会调用未定义的行为?