C++:从基类型指针确定派生类型

标签 c++

背景:

参见 this question in the C++ FAQ对于我需要解决的类似情况,但使用命名构造函数。

我有一个基类,B 类

我有一个来自 B 的派生类,D 类它通过函数、成员和额外的内存分配添加了额外的功能

class B 通过不执行任何操作或从特定于 class D< 的虚函数返回默认值和 nullptrs 以多态方式支持附加功能.

B 类 使用public static Factory Methods 来构造所有 protected 构造函数。 (参见:Named Constructor Idiom)

D 类 使用public static Factory Methods 构造所有protected constructors,这些构造函数的名称与 B 类不同,并且在 B 类中不可用.

一段时间后,创建了一个新的接口(interface)类,class A。此类有一个接口(interface),这样来自 class A 的派生类必须有一个 getter 函数和一个 setter 函数,它们都需要一个 pointer to a class B 但动态值可以是 class Bclass D

问题:

我想派生 class A 并为 class B 创建复制构造函数、赋值运算符和/或 setter,但是因为 class A 仅将其成员公开为 B 类型的对象 我无法确定返回的对象是 class B 还是 class D.

我如何仅使用公共(public)接口(interface)正确实现上述内容而不会导致切片或内存问题(包括如果上述设置错误且需要更改)?

可能的解决方案?

我很想尝试几个选项:

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 的虚拟方法,我知道当在 class B 对象上使用时返回 nullptr:

if(getB()->VirtualMethodSpecificToClassD() == nullptr) {
    //Call B::CreateB(...)
} else {
    //Call D::CreateD(...)
}

这三种情况都有代码味道:

  1. 导致“else-if-heimers”。
  2. 不太确定这是否真的有效。
  3. 违反了“代码到接口(interface)而不是实现”的良好做法。

最佳答案

根据 zneak 的评论,我认为如果您使用工厂方法和私有(private)构造函数,那么拥有一个

 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 开销。

关于C++:从基类型指针确定派生类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19782588/

相关文章:

c++ - 在 C/C++ 中为什么 do while(expression);需要半冒号吗?

c++ - 如何让我的 vector 类支持直接初始化/赋值

c++ - 代码按下的按钮

c++ - 如何修复 ifstream 的段故障核心转储错误

c++ - Qt QOpenGLWidget wheelEvent 奇怪的行为

c++ - C++中没有指针的循环引用

c++ - 构造 'new'对象时出现异常,堆分配的内存会怎样?

c++ - 一维谐振子递归函数,可能无限循环,c++ 语法

c++-设置一个接受值列表的数组

c++ - 虚幻引擎: How can I create UStaticMeshComponent in a loop?