提问人:Raff89 提问时间:10/2/2023 更新时间:10/2/2023 访问量:54
返回对多态对象的引用
Returning reference to polymorphic object
问:
我读到对对象的引用保留了多态行为,考虑到这一点,我开始根据函数调用和各种回调中传递的 const 引用构建一个事件框架,它工作得很好,直到我需要从函数中获取事件作为返回。请考虑以下代码:
#include <iostream>
#include <memory>
class Base
{
public:
inline Base(int type) : m_type(type){}
virtual ~Base(){};
virtual int method() const = 0;
int m_type;
};
class Derived1 : public Base
{
public:
inline Derived1(const int data)
: Base(1)
, m_data(data){}
virtual inline int method() const override {return m_data;}
int m_data;
};
// class Derived2 ...
// class Derived3 ...
// class Derived4 ...
const Base* ptr_factory()
{
const Derived1* product = new Derived1(5);
return product;
}
const Base& ref_factory()
{
const Derived1 product(5);
return std::move(product);
}
void do_the_thing(const Base& data)
{
// if m_type is 1
const Derived1& data_cast = dynamic_cast<const Derived1&>(data);
std::cout<<"Hello World " << data.method();
}
int main()
{
// pointer
std::unique_ptr<const Base> ptr;
ptr.reset(ptr_factory());
do_the_thing(*ptr);
return 0;
// reference
// cannot create Base object here, because abstract, and cannot create Derived because I do not yet know which one
const Base& ref = ref_factory(); <- undefined behavior and lots of sadness
do_the_thing(ref);
return 0;
}
基于引用的ref_factory会产生未定义的行为,我知道,std::move实际上并没有移动任何东西,只是给了我一个对已经被摧毁的本地对象的引用(和虚假的希望)。 我的问题是:有没有办法在给定的场景中避免指针? 我甚至无法在 main 中创建一个空的、默认构造的对象,因为基类是抽象的(即使不是,派生的数据也可能在以后被切片)。我也无法在 main 中创建 Derived 对象,因为工厂本身只知道它最终会是什么实际类型。 在你问我对指针有什么好处之前 - 我没有,但只要看看代码在基于引用的部分上看起来有多干净。 理想的解决方案是让ref_factory创建对象并将对象的所有权移至 main。 这在 C++14 中是否可能,或者我是否坚持必须在框架的这一部分中使用指针和新功能?
答:
我的问题是:有没有办法在给定的场景中避免指针?
当然,您可以返回一个值类型对象,该对象内部包含指向动态对象的指针(或引用)。如果它除了管理所包含的动态对象的生存期之外什么都不做,那么除了 though 之外,它没有任何实际意义。unique_ptr<Base>
理想的解决方案是让ref_factory创建对象并将对象的所有权移至 main。
核心准则普遍倾向于用于表示(和转让)所有权(R.20-21),并且还建议原始指针和引用都不应拥有(R3和R4)。unique_ptr
你绝对可以编写一个新的 RAII 值对象,其中包含对你的动态类型的拥有引用,但要使一些不那么标准和更令人惊讶的东西会是额外的工作。
这在 C++14 中是否可能,或者我是否坚持必须使用指针和新
无论如何,您都不应该使用原始指针和表达式。请改用 and。唯一指针本身可以很好地移动,如果您甚至不想在 中看到 ptr,您可以给它一个 或 type 别名。new
std::unique_ptr<Base>
std::make_unique<Base>(...)
typedef
using
unique_ptr
评论
std::move
unique_ptr<Base>
.
->
const Base& ref_factory() { static std::vector<std::uniqie_ptr<Base>> v; v.emplace_back(std::make_unique<Derived>(); *return v.back();}