使用unique_ptr的多态类的C++static_cast和dynamic_cast
C++ static_cast and dynamic_cast of polymorphic classes using 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 Bn";
}
void get()
{
cout<<"enter b: ";
cin>>b;
}
void disp()
{
cout<<"b = "<<b<<"n";
}
~B()
{
cout<<"destroying Bn";
}
};
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 successfulnn";
}
catch (exception &e)
{
cout<<"dynamic_cast unsuccessful: "<<e.what()<<"nn";
}
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 successfulnn";
}
catch (exception &e)
{
cout<<"static_cast unsuccessful: "<<e.what()<<"nn";
}
pa.reset(pb.release());
}
int main()
{
cout<<R"(using "unique_ptr<A> pa with new A" :-)"<<"nn";
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" :-)"<<"nn";
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
我只有两个问题,因为我已经标记:-
为什么第一个对象{用(1)表示}没有被破坏,而用"新B"调用的对象却被破坏了?
为什么(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 successfulnn";
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()<<"nn";
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
。
如果你这样做,你的两个问题都解决了
相关文章:
- 如何理解C++标准N3337中的expr.const.cast子句8
- 为什么即使使用-cudart-static进行编译,库用户仍然需要链接到cuda运行时
- C++Cast运算符过载
- 如何处理 c++ 中类实现中的"invalid use of non-static data member"?
- 收到错误"invalid use of non-static data member 'stu::n' "
- LNK1104:无法打开libpjproject-i386-Win32-vc14-Debug-Static.lib
- 我应该在 C++ 中何时/为什么使用 STATIC?
- 在VS2019项目中集成ImageMagick:x64-windows-static library
- 如何处理Boost Spirit X3导致Visual Studio 2019 "static initialization order fiasco"?
- "static char __ = []() -> char"的含义
- 当初始值设定项是基类名时'initializer does not name a non-static data member or base class'错误
- 无法在 DLL 中链接 SDL2-static.lib
- 如何摆脱C++中未解析的外部符号"private: static char"错误?
- 错误:"cast"未命名类型void setCastDescription(std::string
- 通过使用 const-cast 的非常量引用来延长临时的寿命
- C++线程"Call to non-static member function without an object argument"
- 出现这种错误的原因是什么"invalid use of non-static data member "
- "(void) cast"与功能有什么区别 "__attributes__"来沉默未使用的参数警告?
- static是如何使用ClassA::m_variable处理所有类对象的
- 在[expr.static.cast]/4中,术语"一个可行函数"指的是什么