【发布时间】:2018-11-19 02:10:58
【问题描述】:
我有一个案例,我想为空间搜索结构公开一个干净的 API。
现在,我很方便地在这个玩具示例中代表了更大的情况。
这里有两个抽象基类ToySmall和ToyBig,派生类型ToySmall的实例是在returnSmall方法中创建的ToyBig的实例派生类型。
以下是ToyInterface.h的内容
#include <iostream>
#include <memory>
class ToySmall
{
public:
ToySmall() {}
virtual void toyMethod() const = 0;
};
class ToyBig
{
public:
ToyBig() {}
virtual std::unique_ptr<ToySmall> returnSmall() = 0;
};
我将returnSmall 的返回类型设为std::unique_ptr<ToySmall>,以便返回协变类型,因为ToyBig 的每个派生类型都返回不同的ToySmall 派生类型。
但是在实现这些接口并按照我的意图使用它们时,我在获取ToySmallImpl 的具体实例时遇到了问题,如下面的文件中所示。我在下面的源代码中包含了错误。
#include <iostream>
#include "ToyInterfaces.h"
class ToySmallImpl : public ToySmall
{
public:
ToySmallImpl()
: ToySmall()
{}
void toyMethod() const override
{
std::cout << "All Good!!" << std::endl;
}
};
class ToyBigImpl : public ToyBig
{
public:
ToyBigImpl()
: ToyBig()
{}
std::unique_ptr<ToySmall> returnSmall() override
{
ToySmall* small;
ToySmallImpl smallImpl;
small = &smallImpl;
return std::unique_ptr<ToySmall>(small);
}
};
int main()
{
ToyBigImpl bigImpl;
std::unique_ptr<ToySmall> toySmall = bigImpl.returnSmall();
// ToySmallImpl toySmallImpl = *toySmall;
// Error : error: conversion from ‘ToySmall’ to non-scalar type ‘ToySmallImpl’ requested
ToySmallImpl toySmallImpl = static_cast<ToySmallImpl>(*toySmall);
// Error : no matching function for call to ‘ToySmallImpl::ToySmallImpl(ToySmall&)’
toySmallImpl.toyMethod();
}
由于Impl 类是从我拥有的接口扩展而来的,并且也可以由其他开发人员实现,我不想像大多数其他解决方案那样拥有复制构造函数或= 运算符.如果它只是为了我,我会非常高兴地让它工作,但我可以。但是,我希望它是干净的,以便我可以将解决方案作为指南提供给 API 的其他用户。
我想知道是否有其他人有类似的情况,可以指出一个可能的解决方案,在 main 中,我将能够创建 ToySmallImpl 的实例并使用它。
【问题讨论】:
-
您的
returnSmall()正在返回本地对象的地址,尽管它包含在std::unique_ptr中。这意味着调用者会收到一个指向不再存在的对象的指针 - 因此调用者对该对象的任何使用都会产生未定义的行为。当返回的unique_ptr超出范围时,这也意味着未定义的行为,因为它试图释放不再存在的对象。
标签: c++ c++11 inheritance design-patterns