C ++:包含继承,多态和工厂

时间:2014-09-09 21:16:36

标签: c++ inheritance polymorphism factory

我目前正在尝试制作一对相互依赖的课程。实质上,类B的对象创建类A的对象。但是,我也在使用继承层次结构,因此类B的所有派生词也必须能够创建类A的派生词(B的每个派生词都对应A的派生词1}},因此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
    }
}

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

我希望我的用户(程序员)以相同的方式与所有A个对象进行交互。它们将具有完全相同的公共函数,但每个函数都具有非常不同的实现。有些将使用不同的数据类型(因此需要函数契约),但许多将使用相同的数据类型,只是使用不同的算法。如果使用一个类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,其余代码看起来都是一样的(因为每个对象具有相同的公共成员函数,即使每个对象将以不同方式执行这些函数)。

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

感谢您的帮助。我为在一篇文章中提出两个问题并且啰嗦而道歉,但我正在努力学习如何对某些软件进行相当大的重新设计。

1 个答案:

答案 0 :(得分:2)

您有几个语法问题可以解决错误:

  • 在每个类定义后添加;
  • 第一行应该是前瞻性声明: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