使用 unique_ptr 的多态类的 C++ static_cast 和 dynamic_cast

标签 c++ casting unique-ptr

我在 C++ 的多态类上练习 static_cast 和 dynamic_cast。我尝试使用原始指针和 unique_ptr。虽然前者不会产生问题,但后者会产生问题。在这里我展示我的代码:-

#include <iostream>
#include <memory>
#include <exception>
#include <stdexcept>
using namespace std;

class A
{
    int a, id=0;
    static int i;
public:
    A()
    {
        id=++i;
        cout<<"constructing A: "<<id<<"\n";
    }
    virtual void get()
    {
        cout<<"enter a: ";
        cin>>a;
    }
    virtual void disp()
    {
        cout<<"a = "<<a<<"\n";
    }
    virtual ~A()
    {
        cout<<"destroying A: "<<id<<"\n";
    }
};
int A::i=0;
class B: public A
{
    int b;
public:
    B()
    {
        cout<<"constructing B\n";
    }
    void get()
    {
        cout<<"enter b: ";
        cin>>b;
    }
    void disp()
    {
        cout<<"b = "<<b<<"\n";
    }
    ~B()
    {
        cout<<"destroying B\n";
    }
};

void show (unique_ptr<B> &p)
{
    p->get();
    p->disp();
}
void d_cast (unique_ptr<A> &pa)
{
    unique_ptr<B> pb;
    try
    {
        pb.reset(dynamic_cast<B*>(pa.release()));
        if (pb==nullptr)
            throw runtime_error {"nullptr exception"};
        show(pb);
        cout<<"dynamic_cast successful\n\n";
    }
    catch (exception &e)
    {
        cout<<"dynamic_cast unsuccessful: "<<e.what()<<"\n\n";
    }
    pa.reset(pb.release());
}
void s_cast (unique_ptr<A> &pa)
{
    unique_ptr<B> pb;
    try
    {
        pb.reset(static_cast<B*>(pa.release()));
        if (pb==nullptr)
            throw runtime_error {"nullptr exception"};
        show(pb);
        cout<<"static_cast successful\n\n";
    }
    catch (exception &e)
    {
        cout<<"static_cast unsuccessful: "<<e.what()<<"\n\n";
    }
    pa.reset(pb.release());
}

int main()
{
    cout<<R"(using "unique_ptr<A> pa with new A" :-)"<<"\n\n";
    unique_ptr<A> pa(new A);    // (1)
    d_cast(pa);
    s_cast(pa);      // (2)
    cout<<"\n"<<R"(using "unique_ptr<A> pa with new B" :-)"<<"\n\n";
    pa.reset(new B);
    d_cast(pa);
    s_cast(pa);
    return 0;
}

代码的输出是:-

using "unique_ptr<A> pa with new A" :-

constructing A: 1
dynamic_cast unsuccessful: nullptr exception

static_cast unsuccessful: nullptr exception


using "unique_ptr<A> pa with new B" :-

constructing A: 2
constructing B
enter b: 7
b = 7
dynamic_cast successful

enter b: 8
b = 8
static_cast successful

destroying B
destroying A: 2

我已经标记了 2 个问题:-

  1. 为什么第一个对象{表示为 (1)} 没有被销毁,而用“new B”调用的对象被销毁了?

  2. 为什么 (2) 抛出异常?有趣的是,如果我颠倒 s_cast(pa)d_cast(pa) 的位置,那么 (2) 不会抛出任何异常并且工作正常(问题 (1) 仍然存在但是)。

最佳答案

好的!所以你需要改变你的功能d_cast像这样的函数定义:-

void d_cast (unique_ptr<A> &pa)
{
unique_ptr<B> pb;
A *aptr=pa.release();   // make a pointer of type A
try
{
    pb.reset(dynamic_cast<B*>(aptr));   // assign aptr instead of pa.release() here
    if (pb==nullptr)
    throw runtime_error {"nullptr exception"};
    show(pb);
    cout<<"dynamic_cast successful\n\n";
    pa.reset(pb.release());   // reset pa with pb.release() and not with aptr becomes pb has the ownership of aptr
}
catch (exception &e)
{
    cout<<"dynamic_cast unsuccessful: "<<e.what()<<"\n\n";
    pa.reset(aptr);    // reset aptr back to pa as pb holds no ownership of aptr
}
}

您一定知道 d_cast会失败,因此 dynamic_cast<B*>(pointer_of_type_A) 的表达会返回 nullptr .如果有一个引用而不是指针,那么 std::bad_cast会抛出异常。但是因为你使用的是 release()函数,unique_ptr 对象 pa摆脱了指针的所有权,并且没有对象或指针可以追溯到它。因此你应该使用 A *aptr持有释放的指针并将其返回到pa如果类型转换失败。

如果你这样做,你的两个问题都解决了

关于使用 unique_ptr 的多态类的 C++ static_cast 和 dynamic_cast,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31080563/

相关文章:

c++ - 不清楚最烦人的解析

c++ - Box2d 错误 C :\filepath\box2D. lib 不是有效的 Win32 应用程序

flutter - 类型 '_InternalLinkedHashMap<String, dynamic>' 不是类型转换中类型 'Map<String, String>' 的子类型

从字符串转换为 float

C++17:unique_ptr<char[]> 和shared_ptr<char[]> 之间指针存储的差异

c++ - C++ 中的 Linux 控制台命令(gcc 编译器)

c - 出于什么原因 printf 不能正确显示 float ?

C++11 非拥有引用/指向 unique_ptr 的指针?

c++ - 带有 unique_ptr 的工厂模式

c++ - 在 OpenCV FOURCC 编解码器中写入视频