具有可变返回类型的纯虚拟函数的功能-解决方法/设计
Functionality of a pure virtual function with variable return type - workaround/design?
我正在开发一个非常非常简单的数据访问层(DAL),它具有两个类:DataTransferObject
(DTO)和DataAccessObject
(DAO)。这两个类都是抽象基类,需要针对特定用例进行继承和修改。
class DataTransferObject {
protected:
//protected constructor to prevent initialization
};
class DataAccessObject {
public:
virtual bool save(DataTransferObject o) = 0;
virtual DataTransferObject* load(int id) = 0;
};
在来自业务逻辑层的House
类的情况下,DAL类的实现将读取以下内容:
class Dto_House : public DataTransferObject {
public:
int stories;
string address; //...which are all members of the House class...
Dto_House(House h);
};
class Dao_House : public DataAccessObject {
public:
bool save(Dto_House h) { /*...implement database access, etc...*/ }
Dto_House* load(int id) {/*...implement database access, etc...*/ }
};
EDIT:当然,派生类知道House
类的结构和数据存储。简单,漂亮,okidoke。现在我想在DTO类中提供一个方法toObject()
,以便将Dto_House
快速转换为House
对象。然后我阅读了C++14中的自动返回类型推导,并尝试了:
class DataTransferObject {
public:
virtual auto toObject() = 0;
};
但我不得不发现:虚拟函数没有自动返回类型推导(
对于这种特定情况,您对实现"推导返回类型的虚拟函数"有什么想法我想在我的DTO"界面"中有一个通用的toObject()
函数。
我唯一想到的是这样的事情:
template <typename T>
class DataTransferObject {
virtual T toObject() = 0;
};
class Dto_House : public DataTransferObject<House> {
public:
int stories;
string address;
House toObject() {return House(stories, address);}
};
编辑:一个可能的用例是:
House h(3, "231 This Street");
h.doHouseStuff();
//save it
Dto_House dtoSave(h);
Dao_House dao;
dao.save(dtoSave); //even shorter: dao.save(Dto_House(h));
//now load some other house
Dto_House dtoLoad = dao.load(id 2);
h = dtoLoad.toObject();
h.doOtherHouseStuff();
但这所房子不知道它是可以保存和装载的。
当然,可以派生抽象的DAO类来进一步完善它,以便与例如Sqlite、XML文件或其他文件一起使用。。。我只是介绍了一个非常基本的概念。
设置一个空的抽象类——实际上是一个接口,然后让两种类型都实现它,并将其设置为toObject
返回引用类型,怎么样?
class Transferable
{
virtual ~Transferable() = 0;
}
然后:
class DataTransferObject {
public:
//Return a reference of the object.
virtual Transferable& toObject() = 0;
};
Dto_House : public DataTransferObject, Transferable { /*...*/ }
House : public DataTransferObject, Transferable { /*...*/ }
上面的例子就是为了说明我的观点。更好的是,您可以使用DataTransferObject
作为返回的引用类型,而不使用其他抽象类:
class DataTransferObject {
public:
virtual DataTransferObject& toObject() = 0;
};
Dto_House : public DataTransferObject { /*...*/ }
House : public DataTransferObject { /*...*/ }
更新:如果你想把类分开,按照约定分离数据和操作之间的任何关联,你可以在表示数据的东西上设置基类的名称,即:Building、Constructionetc,然后将其用于toObject
中的引用类型。
您还可以让类在数据操作的API上操作这些操作。
通常,virtual
函数不能在不同的子类中返回不同的类型,因为这违反了静态类型语言的整个概念:如果调用DataTransferObject::toObject()
,编译器直到运行时才知道它将返回什么类型。
这突出了设计的主要问题:为什么你需要一个基类?你打算如何使用它?调用DataTransferObject::toObject()
,即使你使用了一些魔法(或使用动态类型语言),听起来也不是一个好主意,因为你不能确定返回类型是什么。无论如何,你都需要一些类型转换或if
s,等等,要使其正常工作,或者您将只使用所有此类对象(House
、Road
等)的公共功能,但您只需要为所有这些对象提供一个公共基类。
事实上,同一返回类型规则有一个例外:如果您返回一个指向类的指针,则可以使用协变返回类型概念:子类可以重写virtual
函数以返回原始返回类型的子类。如果你所有的"对象"都有一个公共基类,你可以使用类似的东西
struct DataTransferObject {
virtual BaseObject* toObject() = 0;
};
struct Dto_House : public DataTransferObject {
virtual House* toObject() { /*...*/ } // assumes that House subclasses BaseObject
};
然而,这仍然会留下同样的问题:如果你的代码中只有DataTransferObject
,即使你(而不是编译器)知道它是Dto_House
,你也需要一些类型转换,这可能是不可靠的。
另一方面,您的模板解决方案似乎很好,只是您将无法显式调用DataTransferObject::toObject()
(除非您知道对象的类型),但正如我所解释的,这是一个坏主意。
因此,我建议您考虑如何实际使用基类(甚至编写一些示例代码),并在此基础上做出选择。
- 两个文件使用彼此的功能-如何解决
- C++功能泄漏内存,我是C++新手,不确定如何解决
- OpenCV 错误的解决方案:不支持的格式或格式组合 - 当将 ORB 功能与 FlannBasedMatcher 匹配
- C++ 由于无法解决过载功能而导致绑定失败
- G 无法解决模板功能过载
- 如何解决访问不同功能的"nonstatic member reference must be relative to a specific object"
- 虚拟静态函数功能的解决方法
- 如何在我的指针和阵列功能中修复未解决的外部错误-LNK2019和LNK1120
- 错误LNK2019:未解决的外部符号-MSVC调试构建功能模板
- 类功能中未解决的外部符号
- 虚拟模板功能解决方法
- 控制达到非空功能结束.我该如何解决这个问题
- 无法解决的功能'srand'?(我正在使用 Ubuntu OS 和 Eclipse)
- 与操作员'<<'不匹配 有人可以帮助解决无效功能错误吗?[C++]
- 具有进程间通信功能的服务器-客户端日志记录体系结构.你知道解决方案吗?
- Eclipse CDT 抱怨未解决的功能,但仍然成功构建
- 禁止虚拟模板功能的解决方法
- 具有可变返回类型的纯虚拟函数的功能-解决方法/设计
- 使用VideoWriter_GPU时如何解决OpenCV错误"功能未实现(当前构建或平台禁用了称为功能)?
- LNK2019在功能中未解决的外部符号引用