倾向于在c ++中徘徊[重复]

问题描述 投票:1回答:4

这个问题在这里已有答案:

我有下一个代码

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;
}

代码未编译,因为Shape不是Circle(向下转换错误)。

我有点困惑。 create()不是动态绑定吗?这条线

Circle* cp  = sp->create();  

不应该回圆*?

c++ g++
4个回答
1
投票

向下倾斜不是隐含的。既然你知道你在做什么(即sp实际上是circle),请使用dynamic_Cast

Circle* cp  = dynamic_cast<Circle*>(sp->create());

1
投票

这是因为那条线

Circle* cp = sp->create();

由编译器在编译时进行评估。在编译时,它所知道的是sp是指向Shape的指针,因此Shape::create()的签名在编译时使用。它无法知道指针指向的是什么,因为它是在运行时分配和设置的。要绕过它,请使用dynamic_cast

Circle* cp = dynamic_cast<Circle*>(sp->create());


0
投票

您在具有静态类型create()的实例上调用Shape。因此,函数签名是Shape* create()。实际上,在vtable查找之后,调用的实际函数是Circle::create(),但是将Circle实例存储为Shape引用的点是隐藏具体类型,其成员函数以及可能的协变返回类型。

要通过Circle获得Circle::create()对象,您也可以

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>,这对于返回多态类实例的工厂函数来说是一种很好的做法。


0
投票

将形状指针转换为圆形。

Circle* cp  = (Circle* sp)->create();  
© www.soinside.com 2019 - 2024. All rights reserved.