假设我有以下类:
class X;
class Y;
class Collection
{
public:
virtual void AddItemX(X*) = 0;
virtual void AddItemY(Y*) = 0;
//So on...
};
class Collector
{
public:
virtual void Fill(Collection&) = 0;
};
有没有办法确保Collector
类的实现将填充传递的Collection
类中的所有必需项?
答案 0 :(得分:3)
给定已知数量的AddItemX()调用的一种方法是将这些AddItem()函数移动到受保护的并使Collection类跟踪添加和数字,例如:
(我实际上不喜欢这个解决方案,哈哈,但考虑到你的设计就足够了:)。
class X;
class Y;
class Collection
{
private:
int m_nItems;
int m_nItemsAdded;
protected:
virtual void AddItemXImpl(X&) = 0;
virtual void AddItemYImpl(Y&) = 0;
public:
Collection() : m_nItems(2), m_nItemsAdded(0){};
void AddItemX(X& _x) {m_nMethodsAdded++; AddItemXImpl(_x); };
void AddItemY(Y& _y) {m_nMethodsAdded++; AddItemYImpl(_y); };
// function to find out if we're filled
bool isFilled() const {return(m_nItemsAdded == m_nItems); };
}; // eo class Collection
编辑:为了澄清,您的收藏家可以这样实施:
class Collector
{
protected:
virtual void FillImpl(Collection& _collection) = 0;
public:
void Fill(Collection& _collection)
{
FillImpl(_collection);
if(!_collection.isFilled())
throw(std::exception("Not filled dammit!"));
};
}; // eo class Collector
答案 1 :(得分:2)
答案 2 :(得分:1)
你错过了上面的东西,叫什么叫Collector :: Fill()?在那里你需要检查收集已被填充......
编辑:您是否可以控制调用Collector :: Fill()的位置?这是唯一可以检查集合是否已正确填充的地方。另一个选择是按值传递所有内容,并在复制构造函数(或赋值)中检查..答案 3 :(得分:1)
答案 4 :(得分:1)
当您为将来的开发人员实施一种方法时,您放弃的一件事就是控制他们如何做到这一点。您可以添加一条评论来提出您的建议,但是他们可以根据他们的子类做适当的评论。毕竟,你永远无法确定你的课程将如何在路上使用。
答案 5 :(得分:0)
您可以修改类定义以鼓励正确使用,方法是在Collection
构建时检查Collector
有效性,禁止Collector
的默认构造或修改封装的Collection
。让Collector
构造函数使用纯虚方法验证收集器。
这并不保证正确性 - Collection
实现者仍然可以通过允许格式错误的子类来作弊 - 但通过更清楚地表达您想要的内容来支持它。
class X;
class Y;
class Collection
{
public:
virtual void AddItemX(X*) = 0;
virtual void AddItemY(Y*) = 0;
//So on...
virtual bool ensureValid() = 0;
};
class Collector
{
public:
Collector (const Collection coll&) : _coll(coll)
{
if (!coll.ensureValid())
{
// throw an error
}
}
private:
Collector();
protected:
const Collection _coll;
};