0

假设我们有一个 Collection 类,例如:

class CCollection {

public:
    void add(B& b);
    void remove(B& b);
    void doSomethingWithAllObjects();

protected:
    std::vector<B*> bs;

}

其中 B 是一个抽象类,其具体行为

doSomethingWithAllObjects();

取决于B的具体类型,称之为C。

有没有办法派生 CCollection 并让方法

add(B b);
remove(B b);

只接受派生类型?

我想到了像这样覆盖这样的方法:

class D : A{
public:
    void add(C c);
    void remove(C c);
    void doSomethingWithAllObjects();
private:
    std::vector<B*> bs;      
}  

或通用的 javaish 构造,例如

template<class T : B>
class C {
    ...//do lots of stuff
}

推导几乎 100% 相同。但是你不能混合 B 的不同派生。

我已经读过几乎不可能将模板类限制为某些类型,但是必须有一种方法可以避免为 B 的每个派生编写整个类。关键是,我需要在 B 中定义的函数,所以我不能使用一个简单的模板

template<class T>
class B{
  ....
} 

当然,我可以假设其他程序员只是将正确的类型交给正确的 CCollection,但这不是精神。我想要的是强迫其他程序员只添加一种类型的 B。

4

2 回答 2

0

我不确定我是否理解正确,但我认为您正在寻找一个简单的模板非成员类型函数。模板函数可用于确保类型匹配。

template<typename T>
void global_adder(const T& cl, const T& toadd) {
    cl.add(toadd);
}
  • 由于不基于继承进行类型推导,这将确保 A 不添加到 B 或 B 到 C 等等。要添加的两个 args 必须具有相同的类型。而已。

  • 您仅将类方法保留在基类中。制作它 protected并将此功能添加为friend.

  • 这样,您现在将没有人可以调用a.addb.add从其他地方调用(将无法向某个类添加不同的类型)。

  • 添加或删除元素的唯一方法是通过确保类型匹配的模板函数。

于 2013-04-21T17:17:04.657 回答
-1

您可以制作一个抽象基集合类,例如

class BaseCollection {
  public:
    void doSomethingWithAllObjects();
  protected:
    void addInternal(B* b); // consumes the element

    std::vector<B*> bs;  // or better use vector<shared_ptr> for reference count
};

template <typename C>
class Collection : public BaseCollection {
  public:
    void add(const C& c) {
      C* my_copy = new C(c);  // suppose we have a copy constructor
      addInternal(my_copy);
    }
};

如果你试图实例化Collection<C>whereC不是 的子类B,你会得到一个编译错误。

于 2013-04-21T16:45:33.827 回答