gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:10:51 24 4
gpt4 key购买 nike

背景:

参见 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/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com