通过make_unique取消引用下载的派生对象是否安全?

时间:2015-02-05 20:34:40

标签: c++ c++11 casting c++-cli derived-class

我有一个基类和一个派生类,以及一个返回对基类的引用的函数。使用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;
}

2 个答案:

答案 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:被遗忘了。在这种情况下,您不会收到无法访问的警告,您只会遇到演员失败。一切看起来都不错,但链条坏了。

也许这可能会节省其他人遇到类似问题的时间。