2013-04-21 131 views
0

比方说,我们有一个集合类,如:覆盖功能参数/

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但是这不能成为精神。我想要的是强制其他程序员只添加一种类型的Bs。

+0

欢迎来到Stack Overflow!如果我正确地阅读你的问题,似乎有一个基本的设计问题。虚拟函数允许在* runtime *处确定行为。并且,在运行时条件已知之前,更改该参数的类型将在编译时执行。你希望在编译时执行什么? – 2013-04-21 16:41:11

+0

只接受派生类型?是不是基类抽象?你不能声明它的一个对象。那么你怎么能通过它来添加和删除?我在这里错过了什么吗? – stardust 2013-04-21 16:44:12

+0

我不确定你是如何从值参数'add(B b)'转换成一个存储在你的向量中的指针'std :: vector '似乎你可以采取的唯一的地址是参数的死亡地址函数结尾'add()' – 2013-04-21 16:46:03

回答

0

我不知道如果我理解正确的,但我想你loooking一个简单模板非成员函数型。模板函数可以用来确保类型匹配。

template<typename T> 
void global_adder(const T& cl, const T& toadd) { 
    cl.add(toadd); 
} 
  • 由于没有做基于遗产类型扣减,这将 确保A不添加到B或B到C等。要加入 这两个参数必须具有相同的类型。而已。

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

  • 这样,你现在没有人可以调用从 别的地方a.addb.add将不能够在不同类型添加到一定 类)。

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

+0

完美的作品。谢谢! – 2013-04-21 20:16:05

-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>其中C不是B一个子类,你会得到一个编译错误。

+0

不要将指针传入集合。要么传递一个引用,从而表明你没有获得所有权(然后将其转换为存储在bs中的指针)。或者传递一个智能指针,指示您正在获取所有权(由智能指针的类型定义)。 – 2013-04-21 16:48:52

+0

矢量并不是更好。您正在混合所有权语义。定义允许您定义存储标准的所有权语义。 – 2013-04-21 16:50:11

+0

这正是我想要避免的,因为我有大量的重复代码用于每个新的派生。我刚刚发布了一个例子。我真正的收藏类有点复杂;-) – 2013-04-21 17:01:11