C++:结合继承、多态和工厂

标签 c++ inheritance polymorphism factory

我目前正在尝试创建一对相互依赖的类。本质上,类 B 的对象创建类 A 的对象。但是,我还使用了继承层次结构,因此类 B 的所有派生类也必须能够创建类 A 的派生类(B 的每个派生类code> 对应于 A 的派生,因此 DerB1 生成 DerA1 对象,而 DerB2 生成 DerA2 对象)。

我的实现有问题,这可能很愚蠢,但我想看看是否有人知道该怎么做。我的代码在下面(我讨厌阅读别人的代码,所以我试图让它尽可能容易阅读......只有几个重要的部分,我评论解释)

class BaseB {} // Declare BaseB early to use in BaseA constructor

class BaseA
{
public:
BaseA(BaseB* b) {}; // Declare the BaseA constructor (callable by all B classes, which pass a pointer to themselves to the constructor so the A objects can keep track of their parent)
}

class DerA:public BaseA
{
    DerA(BaseB* b):BaseA(b) {}; // Inherit the BaseA constructor, and use initialization list
}

class BaseB
{
public:
    virtual BaseA createA() = 0; // Virtual function, representing method to create A objects
}

class DerB:public BaseB
{
    BaseA createA() {
        DerA* a = new DerA(this); // Definition of createA to make a new A object, specifically one of type DerA (Error1: No instance of constructor "DerA::DerA" matches the argument list)
        return a; // Error2: Cannot return DerA for BaseA function
    }
}

所以,我有两个主要问题,一个是实际问题(错误 1,因为我似乎只是错误地调用了函数,即使我尝试类型转换 this),一个是哲学问题(错误 2 ,因为我不知道如何实现我想要的功能。如果有人能指出为什么会出现 Error1,那就太好了!但是,Error2 需要一些解释。

我希望我的用户(程序员)以相同的方式与所有 A 对象进行交互。它们将具有完全相同的公共(public)函数,但每个函数将具有非常不同的实现。有些将使用不同的数据类型(因此需要函数契约),但许多将具有相同的数据类型,只是它们使用的算法不同。如果使用一个类 A 派生类或另一个类,我希望一些代码以完全相同的方式工作。但是,在我当前的实现中,似乎我需要返回一个 DerA 对象而不是一个 BaseA 对象(在 Error2 的位置)。这意味着我需要专门为 DerA 对象编写一段主代码,而不是任意的 A 对象。我想要这样的东西:

BaseB b = new DerB(); // Declare which derivative of BaseB I want to use
BaseA a = b->createA(b); // Call the createA function in that derivative, which will automatically make a corresponding A object

这样,我可以简单地在第一行中选择我想要的 B 对象类型(通过我选择 B 构造函数、标签或模板,或其他东西),其余代码对于任何类型的对象 B 看起来都是一样的(因为每个对象都有相同的公共(public)成员函数,即使每个对象执行这些函数的方式不同)。

使用模板或其他方法而不是继承会更好吗? (我为故意含糊而道歉,但我希望我的 A/B 类示例应该主要解释我需要什么)。

感谢您的帮助。对于在一篇文章中提出两个问题和啰嗦,我深表歉意,但我正在努力学习对某些软件进行相当大的重新设计的最佳方法。

最佳答案

您有几个语法问题需要解决错误:

  • 在每个类定义之后添加;
  • 第一行应该是前向声明:class BaseB/*{} NO!!*/;
  • 添加 public: 使 DerA 的构造函数可供 DerB 访问
  • BaseA createA() 应该返回一个值,而不是一个指针(根据签名):return *a;

还有另一个潜在的隐藏切片问题,因为createA() 返回一个值,而不是指针。这意味着您返回的对象(此处为 *a)将被复制,但作为真正的 BaseA 对象。因此只会复制对象的 BaseA 部分,不会复制派生部分。这可能会导致一些意想不到的惊喜。

为了避免切片,考虑返回一个指针,相应地更改 createA() 的签名。指向的对象将保持正确的类型而不会丢失任何东西。

如果您稍后需要复制该对象,并且您完全确定所指向对象的真实类型,则可以使用静态转换:

   BaseA *pba = pdb->createA();         // get pointer returned 
   DerA da = *static_cast<DerA*>(pba);  // static cast with pointer

如果您需要复制指向的 BaseA 对象而不必知道它们的真实类型,您可以在 DerA 中实现一个虚拟克隆函数(例如 prototype design pattern)

关于C++:结合继承、多态和工厂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25753687/

相关文章:

c++ - 使用 C++ 向 MYSQL 表中插入字符

c++ - 澄清 Sean Parent 的谈话 "Inheritance is the base class of evil"

delphi - 如何强制后代类实现抽象函数?

java - 接口(interface)中的泛型类型和多态性

c++ - C/C++结构不完整成员类型不一致?

c++ - C 项目 O 文件在 make 期间删除后仍在寻找 Cpp 文件

c++ - 通过位域访问 char 中的位

java - 为什么我在这里得到 ClassCastException?

c++ - 为什么多态类型错误和清理问题?

c++ - 为什么我们实际上需要运行时多态性?