背景:
有关我需要解决的类似情况,但使用命名构造函数,请参阅C++ FAQ 中的这个问题。
我有一个基类,class B.
我有一个来自 B 的派生类class D,它通过函数、成员和额外的内存分配添加了额外的功能。
通过class B什么都不做或返回默认值以及nullptrs从特定于class D.
class B用于public static Factory Methods所有的建筑protected constructors。(请参阅:命名构造函数习语)
class D用于public static Factory Methods所有与protected constructorsB 类命名不同且在 B 类中不可用的构造。
一段时间后,创建了一个新的接口类,class A. 此类具有一个接口,因此派生类class A必须具有一个 getter 函数和一个 setter 函数,它们都需要 apointer to a class B但动态值可以是class B或者class D
问题:
我想派生class A并创建一个复制构造函数、一个赋值运算符和/或一个 setter,class B但因为class A只将其成员公开为类型的对象,B我无法确定返回的对象是否为class Bor class D。
我将如何仅使用公共接口正确实现上述内容而不会导致切片或内存问题(包括如果上述设置错误并且需要更改)?
可能的解决方案?:
我很想尝试几个选项:
1)在B类和声明对象类型的所有派生类型中创建一个成员:
if(getB()->GetType() == "D") {
//Call D::CreateD(...)
} else if(getB()->GetType() == "B") {
//Call B::CreateB(...)
}
2)动态转换为派生类型并检查失败:
if(dynamic_cast<D*>(getB()) == nullptr) {
//Call B::CreateB(...)
} else {
//Call D::CreateD(...)
}
3)使用特定于class D我知道nullptr在class B对象上使用时返回的虚拟方法:
if(getB()->VirtualMethodSpecificToClassD() == nullptr) {
//Call B::CreateB(...)
} else {
//Call D::CreateD(...)
}
这三种情况都有代码味道:
- 导致“else-if-heimers”。
- 不太确定这是否真的有效。
- 违反“代码到接口而不是实现”的良好做法。