2

当您有一个类型取决于某些约束的成员时,您如何设计多态性。

说我有这个:

template<typename T>
class Base
{
public:
  Base() = default;
  virtual ~Base() = default;
  T member;
};

class DerivedA : public Base<int>
{
public:
  DerivedA() {member = 5;}
};

class DerivedB : public Base<float>
{
public:
  DerivedB() = default;
};

我希望能够根据不同的参数创建一个新的派生对象,即:

Base *b;
if (something)
    b = new DerivedA();
else
    b = new DerivedB();

显然我不能这样做,因为我需要为b.

这是糟糕的设计吗?你怎么处理这个?

我可以写一个小包装:

class Wrapper() {};

template<typename T>
class Base : public Wrapper
{
// ...
};

Wrapper a, b;
a = new DerivedA;
b = new DerivedB;

但是我将无法直接访问ormember中声明的其他方法。我需要强制转换 : ,使多态性变得无用。BaseDerivedreinterpret_cast<DerivedA*>(a)->member

谢谢

4

2 回答 2

0

包装设计应该正是您正在寻找的。问题是c++是静态类型的,所以你不能在不指定其类型的情况下声明成员。避免这种情况的常用方法是设计一个支持您想要的所有功能的基类,并在派生类中实现特定行为,就像您所做的那样。

问题可能是您的类不支持您需要的所有功能。尽量避免直接使用 member 并将其用法包装到虚拟方法中。在派生类中重新实现这些方法。

如果这仍然不是一个选项,请考虑提取成员的方法。也许是具有适当转换的虚拟 getter 和 setter。

作为最后的手段,考虑 boost::variant、boost::any。但实际上它们是使用类似于您的包装器的技术实现的。所以你得到了包装器的包装器。

于 2012-12-20T12:20:12.813 回答
0

好吧,如果“访问”取决于模板参数T(例如阅读Base.member),那么您必须以某种方式提供它。转换为派生类之一是一种方法,但您不需要reinterpret_cast. 您需要开始使用指针/引用,以避免中断并让可替代性正常工作:

Wrapper *a, *b;
a = new DerivedA;
b = new DerivedB;

int a_member = static_cast<DerivedA*>(a)->member;
float b_member = static_cast<DerivedB*>(b)->member;

如果你添加一个虚拟方法来Wrapper使其具有多态性,你也可以进行动态转换:

DerivedB* b_derived = dynamic_cast<DerivedB*>(b);
if (b_derived != nullptr) {
    float b_member = b_derived->member;
    // ...
}
于 2012-12-20T13:02:41.740 回答