我有一个基类和一个派生类,以及一个返回对基类的引用的函数。使用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:\Projects\Parsers\View.cpp
Intellisense告诉我,从Value到Title没有合适的用户定义转换。
然而,这可以很好地完成编译,但我不确定这是否安全。
// 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;
}
答案 0 :(得分:0)
你的问题不是你认为的问题。您感到困惑,因为您的代码意味着继承是私有的,并且等同于以下内容:
class Dog : private Animal {}
私人继承,你的狗不是动物。
你真的想要定期继承:
class Dog : public Animal {}
然后你实际上不需要贬低任何东西,因为C ++会为你做这件事。
使用公共继承,以下内容无需任何副本即可运行:
void myFun(Animal&);
int main() {
Dog dog;
myFun(dog);
}
答案 1 :(得分:0)
好的,我找到了原始问题的答案。缺点是:这样做并不安全。它绕过了铸件评估,并且它会在运行时吹出垫圈。
实际问题由于嵌套派生类的数量而变得模糊不清,其中一个在中间,实际上没有一个向下转换构造函数。
实际上,事实证明是这样的:
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或以上的水平(这是我试图达到的目标)。
获得的经验教训:在构建深度派生的对象链时,请务必仔细检查以确保每个类都有向下转换构造函数,并确保它是公共的。
在另一组不同类的另一个实例中,它从一个struct转换为一个类,而Public:被遗忘了。在这种情况下,您不会收到无法访问的警告,您只会遇到演员失败。一切看起来都不错,但链条坏了。
也许这可能会节省其他人遇到类似问题的时间。