我目前正在尝试制作一对相互依赖的类。本质上,类B
的对象创建类A
的对象。但是,我也使用继承层次结构,因此所有B
类的派生类也必须能够创建A
类的派生类(每个B
的派生类都对应于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
对象进行交互。它们将具有完全相同的公共功能,但是每个将具有这些功能的非常不同的实现。有些将使用不同的数据类型(因此需要功能约定),但是许多将具有相同的数据类型,只是使用的算法不同。如果要使用一个类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班级示例应该主要说明我的需求)。
感谢您的任何帮助。我为在一个帖子中问两个问题并为时过长而道歉,但我正在尝试学习最好的方法来对某些软件进行较大的重新设计。
最佳答案
您有几个语法问题可以解决错误:
在每个类定义之后添加;
。
第一行应为前向声明: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++ - C++:整合继承,多态和工厂,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25753687/