通过make_unique取消引用下转换的派生对象是否安全
Is it safe to dereference a downcasted derived object via make_unique?
我有一个基类和一个派生类,以及一个返回基类引用的函数。使用make_unique然后向下转换指针安全吗?
我正在努力避免复制操作。
class Animal {}
class Dog : Animal {}
Animal GetAnimal() { ... }
Dog GetDog() {
Dog dog = *std::make_unique<Dog>( GetAnimal() );
return dog;
}
或者有更直接的方法吗?
编辑:
这是实际的代码(非常接近我上面显示的内容:
// Convert from (m)anaged to (u)nmanaged Title
Title Data::MarshalTitle(TitleMap ^mdefn) {
Title udefn = MarshalValue(mdefn);
return udefn;
}
然后MarshalValue定义为:
Value Data::MarshalValue(TitleMap ^mdefn)
现在,您在这里没有看到Value是一个基类,Title是一个派生类。
我从编译器得到的错误是:
error C2440: 'initializing' : cannot convert from 'Definitions::Value' to 'Definitions::Title' D:ProjectsParsersView.cpp
Intellisense告诉我,没有合适的用户定义的从值到标题的转换。
然而,这可以很好地通过编译器,但我不确定这是否安全。
// Convert from (m)anaged to (u)nmanaged Title Dimension definition
Title Data::MarshalTitle(TitleMap ^mdefn) {
Title udefn = *std::make_unique<Title>(MarshalValue(mdefn));
return udefn;
}
你的问题不是你认为的那样。您感到困惑,因为您的代码意味着继承是私有的,并且等价于以下内容:
class Dog : private Animal {}
有了私人遗产,你的狗就不是动物了。
而您真正想要的是常规继承:
class Dog : public Animal {}
然后你实际上不需要向下转换任何内容,因为C++会为你做这件事。
有了公共继承,以下内容将在没有任何副本的情况下工作:
void myFun(Animal&);
int main() {
Dog dog;
myFun(dog);
}
好的,我找到了原来问题的答案。简而言之:这样做是不安全的。它绕过了铸件评估,并且在运行时会吹坏垫圈。
由于嵌套派生类的数量,而其中一个位于中间的派生类实际上没有下转换构造函数,因此实际问题被掩盖了。
实际上,它是这样的:
class A() {}
class AA() : public A {}
class AAA() : public AA {}
class AAAA() : public AAA {}
这些类中的每一个都有一个定义,大致如下:
class AAAA() : public AAA {
AAAA();
virtual ~AAAA()
// Downcasting constructor
AAAA( const AAA &base ) : AAA(base) {};
}
然而,在类AAA()中,缺少AA的下转换构造函数,但编译器所能报告的只是找不到适用于AAAA(AAA)的构造函数。
事实上,链条断裂了,所以它无法达到AA或以上的水平(这正是我试图达到的)。
经验教训:在构建深度派生的对象链时,请始终仔细检查,以确保每个类都有下转换构造函数,并确保它是公共的。
在另一个不同类集的实例中,它被从结构转换为类,而Public:被遗忘了。在这种情况下,您不会收到无法访问的警告,只会收到强制转换失败。一切看起来都很好,但链条坏了。
也许这可以为遇到类似问题的其他人节省时间。
- 为什么此派生对象无法访问基类的后递减方法?
- 如何在新的派生对象中获取基本对象的数据?
- 如何将成员函数作为参数传递并在派生对象上执行方法列表
- 在没有默认构造函数的情况下创建的派生对象
- OOP 标识派生对象
- 如何创建派生对象的向量?
- 将基类分配给派生对象,反之亦然,以C++以及静态和动态对象之间的差异
- 如何从 Gtk::窗口调用派生对象的析构函数
- 无法在派生对象上运行虚拟函数
- 尝试删除指向派生对象的基指针时断言错误
- 存储在一个通用容器中的派生对象.如何避免铸造
- 将派生对象分配给函数内的基类指针
- 替换派生对象向量中的对象"no matching function to call"
- 派生对象调用的 Base 方法的模板推导
- 用于填充 Base 和派生对象的 shared_ptr 向量的函数模板
- C++ UBSAN 对派生对象产生误报
- 如何验证我是否正在使用C++中的基对象或派生对象
- C++ 构造函数和派生对象
- 将派生对象传递给模板
- 指向派生作品的基本指针,即使派生对象不存在