背景
请参阅this question in the C++ FAQ,了解我需要解决的类似情况,但使用命名构造函数。
我有一个基类class B
。
我有一个来自B的派生类class D
,,它通过函数,成员和额外的内存分配添加了额外的功能。
class B
通过不执行任何操作或从特定于nullptrs
的虚拟函数返回默认值和class D
来多态支持其他功能。
class B
使用public static Factory Methods
构建所有protected constructors
。 (见:Named Constructor Idiom)
class D
使用public static Factory Methods
构建所有protected constructors
,其命名与B类不同,但在B类中不可用。
稍后,会创建一个新的接口类class A
。此类具有一个接口,使得class A
中的派生类必须具有getter函数和setter函数,这两者都需要pointer to a class B
,但动态值可以是class B
或{{1 }}
问题:
我想派生class D
并为class A
创建一个复制构造函数,赋值运算符和/或setter,但因为class B
只将其成员公开为一个对象类型class A
我无法确定返回的对象是B
还是class B
。
如何仅使用公共接口正确实现上述内容而不会导致切片或内存问题(包括上述设置错误并需要更改)?
可能的解决方案?:
我很想尝试几种选择:
1)在B类中创建一个成员,以及声明对象类型的所有派生类型:
class D
2)动态转换为派生类型并检查失败:
if(getB()->GetType() == "D") {
//Call D::CreateD(...)
} else if(getB()->GetType() == "B") {
//Call B::CreateB(...)
}
3)在if(dynamic_cast<D*>(getB()) == nullptr) {
//Call B::CreateB(...)
} else {
//Call D::CreateD(...)
}
对象上使用时,使用我知道返回class D
的{{1}}特定的虚拟方法:
nullptr
所有三个案例都有代码味道:
答案 0 :(得分:2)
根据zneak
的评论,我认为如果你正在使用工厂方法和私有构造函数,那么就没有什么东西可以用了
virtual B* copy() const { return new B(*this); /* calls private B::B(const B&) */ }
类B
中的方法,在类D
中重写(返回一个新的D*
- 在C ++中特别允许使用协变返回类型。
然后你的A
拷贝构造函数可以执行类似
A::A(const A& other) : b(other.getB()->copy()) {}
它应该可以正常工作。
另一方面,如果你更愿意使用你建议的解决方案之一,我认为第一个是最不刺激的 - 虽然我会选择枚举而不是字符串,所以你可以使用简单的switch语句而不是字符串比较。我相信LLVM使用类似这样的东西进行“动态转换”,以避免C ++ RTTI开销。