指针强制转换期间的初始化

Initialization during a pointer cast?

本文关键字:初始化 转换 指针      更新时间:2023-10-16

如果我定义了一个派生类,它有初始化器,但最终使用指针强制转换(即static_pointer_cast),那么我如何在不执行解引用和对象复制的情况下执行初始化器?

#include <string>
#include <memory>
class Base {
public:
    std::string Name;
};
class Derived : public Base {
public:
    std::string Address = "Initialized";
};

int main() {
    auto b_ptr = std::make_shared<Base>();
    b_ptr->Name = "Fred";
    auto d_ptr = std::static_pointer_cast<Derived>(b_ptr);
    fprintf( stdout, "Name: [%s]   Address: [%s]", 
        d_ptr->Name.c_str(),  
        d_ptr->Address.c_str() );  // Address not valid!
}

链接到代码:http://coliru.stacked-crooked.com/a/09f2240abff1556b

处理这个问题的正确方法是什么?

编辑:下面是一些示例代码(当然,比真实的代码简化了很多),它更好地说明了我正在尝试做什么,以及为什么如果有一种方法可以让它发挥作用会很好。

更新的样本代码:http://coliru.stacked-crooked.com/a/cdcc31a4417bb52b

在本例中,我有两个数据源,一个来自源系统,另一个来自内部使用的数据源。我真的不想复制所有的数据,只是在上面叠加一些额外的信息

我不确定是否要使用std::move(正如@MooingDuck所建议的),因为它会对源数据产生影响。。。。我需要更多地探索。但是从这个例子中,不执行复制的好处是显而易见的,并且必须使用"has-a"风格的实现会使后续的对象使用变得尴尬。即:

test_row->Values[0].c_str()   and 
test_row->RowTotal

将变成:

test_row->row->Values[0]    yet still
test_row->RowTotal

也许我认为这一切都错了,有更好的算法可以做到这一点吗?

您可以给Derived一个Base&&构造函数,并使用它将Base的内容移动(浅拷贝)到派生中,从而使原始Base处于"空"状态。

class Base {
public:
    std::string Name;
    //Note: The compiler is generating these invisibly for you:
    //Base() :Name() {}
    //~Base() {}
    //Base(const Base& r) : Name(r.Name) {}
    //Base(Base&& r) noexcept : Name(std::move(r.Name)) {}
    //Base& operator=(const Base& r) : Name(r.Name) {}
    //Base& operator=(Base&& r) noexcept : Name(std::move(r.Name)) {}
};
class Derived : public Base {
public:
    std::string Address = "Initialized";
    Derived() = default;
    Derived(Base&& b) : Base(std::move(b)) {}
};    
int main() {
    auto b_ptr = std::make_shared<Base>();
    b_ptr->Name = "Fred";
    auto d_ptr = std::make_shared<Derived>(std::move(*b_ptr));
    //NOTE AT THIS POINT b_ptr POINTS TO A BASE WHOS Name IS EMPTY
    b_ptr.reset(); //reset to prevent accidental errors with lack of content
    fprintf( stdout, "Name: [%s]   Address: [%s]", 
        d_ptr->Name.c_str(),  
        d_ptr->Address.c_str() );  // Address not valid!
}

请在此处查看它的工作情况:http://coliru.stacked-crooked.com/a/f3a6062f6c459c7c
还可以在此处查看运动证明:http://coliru.stacked-crooked.com/a/f7f6cc4aa06d2746

然而,值得注意的是,我想不出有什么好的理由让你想这么做。听起来你的代码设计得很糟糕。

你不能。成员的大括号或相等的初始值设定项仅由构造函数执行。如果要初始化Derived::Address,则需要实际构造一个Derived对象。但是,不能在Base对象已经占用的空间上构造Derived对象;您必须首先销毁Base对象。

您无法就地更改类型。不要进行额外的初始化,也不要礼貌地询问。这是不可能的。

如果你问自己,这很容易看出

make_shared<Base>分配了多少内存?

相关文章: