gpt4 book ai didi

c++ - friend 、抽象类和工厂模式

转载 作者:搜寻专家 更新时间:2023-10-31 01:51:01 24 4
gpt4 key购买 nike

大家好...

我正在为我公司的一个复杂项目工作,我在该项目中使用了一些复杂的工厂设计模式。省略细节;我有一些类(我称它们为“设备”)只能由“读者”创建:

class DeviceBase // this is a virtual base class
{
public:
//some stuff
friend class ReaderBase; // this is OK and necessary I guess?
private:
DeviceBase(); // cannot create a device directly
//some more stuff
}

class Device1: public DeviceBase // some extended device
{
public:
//some stuff
private:
//some more stuff
}

class Device2: public DeviceBase // some other extended device
{
public:
//some stuff

private:
//some more stuff
}

现在是“Reader”,恰好是设备的工厂:

class ReaderBase
{
private:
DeviceBase[] _devices; // to keep track of devices currently "latched"
public:
// some other methods, getters-setters etc ...

// this method will create the "Devices" :
virtual bool PollforDevice ( DeviceType, timeout) = 0;

}

现在,这是我的工厂类;但它(如您所见)是纯虚拟的。我有特殊的读者继承自这个:

 class InternalReader: public ReaderBase
{
public:
// define other inherited methods by specifics of this reader
bool PollforDevice( DeviceType dt, timeout ms)
{
switch(dt)
{
case Device1: { /* create new device1 and attach to this reader */ } break;
case Device2: { /* create new device2 and attach to this reader */ } break;
}
// show goes on and on...
}
}

class ExternalReader: public Reader
{
public:
// define other inherited methods by specifics of this reader
bool PollforDevice( DeviceType dt, timeout ms)
{
switch(dt)
{
case Device1: { /* create new device1 and attach to this reader */ } break;
case Device2: { /* create new device2 and attach to this reader */ } break;
}
// show goes on and on...
}
}

我使用这种模式的原因是:我正在为一个可以同时连接多个这些“阅读器”的系统编写代码,我必须同时使用它们。

还有这些“设备”:我也可以公开它们的构造函数,每个人都会很高兴;但我想确保它们不是由代码编写者自己创建的(以确保它的其他编码器)

现在问题:

  1. 我应该在每个“设备”中明确声明 ReaderBase 是 friend 吗?或者只在基础上声明“DeviceBase”就足够了?
  2. 我是否应该明确地放入从“ReaderBase”继承的“Readers”也是这些设备的 friend 的每个“设备”,还是只放入 ReaderBase 就足够了?
  3. 不是让整个“ReaderBase”类成为好友,我能否(并且应该)只让成员方法“PollforDevice”成为好友?知道它是一个纯虚方法,是否也会使继承的拷贝成为 friend ?

很抱歉这个问题很长,但我只想说清楚。

提前致谢...

最佳答案

为什么要担心像 DeviceBase 这样的纯抽象基类的可构造性?如果它是一个适当设计的契约或抽象基类,无论如何都无法构造它。除非你必须适应某种你没有提到的框架,否则只需执行与隐藏相反的操作,例如:

struct DeviceBase {
virtual void Foo() = 0;
virtual void Bar() = 0;
virtual ~DeviceBase() = default;
};

顺便说一句,将构造函数或析构函数声明为private 将非常有效地使您的类“密封”。如果由于某种原因 DeviceBase 不是抽象的(在我看来这是一个严重的设计缺陷)使构造函数 protected 而不是 private。您需要打扰的是具体 Device 类的构造函数可访问性。假设您要“发布”这些实现类(即您的库的用户可以访问它们的定义)并且您希望强调禁止直接构造,请使用“访问成语”(我为此发明的名称):

namespace impl_detail {
class DeviceAccess;
}

class ConcreteDevice1 : public DeviceBase {
friend class impl_detail::DeviceAccess;
// implementation of DeviceBase and all other stuff go
// into the "private" section
};

namespace impl_detail {
class DeviceAccess {
template< class TDevice >
static DeviceBase* Create()
{
return new TDevice;
}
};
};

在您的 Reader 类中使用 impl_detail::DeviceAccess::Create 构造 Device 实例,例如:

// Your ExternalReader::PollForDevice...
switch (dt) {
case Device1:
return impl_detail::DeviceAccess::Create<ConcreteDevice1>();
case Device2:
// etc...
}

长话短说,最好的解决方案是根本不发布具体的实现类,其次是某种限制构造的“心理障碍”,例如上面那种……

关于c++ - friend 、抽象类和工厂模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14353551/

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