我目前正在尝试制作一对相互依赖的课程。实质上,类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级示例主要解释我需要的内容。)
感谢您的帮助。我为在一篇文章中提出两个问题并且啰嗦而道歉,但我正在努力学习如何对某些软件进行相当大的重新设计。
答案 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)