有一个标题非常相似的帖子here,但据我所知,实际问题有所不同。
我想知道是否可以强制我编写的类的用户覆盖某个方法,但同时不应该调用此方法(但它只在我的类中调用)
例如,如果我想执行以下操作:
class AbstrDataSource {
private:
int index;
protected:
int currentData;
public:
int getData(){return currentData;}
void loadData(int i){
// check valid index here
if (index != i){doLoad(i);}
this->index = i;
}
virtual void doLoad(int i)=0;
};
在loadData()中,我可以检查索引是否在有效范围内并进行一些簿记,而实际加载必须由用户通过覆盖doLoad()来提供。因为纯虚方法是接口的一部分,所以它们是公共的,但是如何强制doLoad()的实现只对我自己的类可见?
我的想法是将对象隐藏在某个包装器中:
class DataSupplier {
public:
DataSupplier(AbstrDataSource* s) : source(s){}
void loadData(int i){source->loadData(i);}
int getData(){return source->getData();}
private:
AbstrDataSource* source;
};
而不是使用抽象类我使用包装器:
int SomeCalculation(DataSupplier* a,DataSupplier* b){
return a->getData() + b->getData();
}
然而,这并没有真正帮助。让我们说第二个人提供了我的抽象类的实现:
class ImplDataSource : public AbstrDataSource{
public:
void doLoad(int i){this->currentData = i;}
};
然后第三个人仍然可以访问doLoad():
void main(){
AbstrDataSource* ads = new ImplDataSource();
DataSupplier* ds1 = new DataSupplier(ads);
DataSupplier* ds2 = new DataSupplier(ads);
ads->doLoad(10); // <- How to avoid this ??
ds1->loadData(12);
ds2->loadData(12);
SomeCalculations(ds1,ds2);
}
也许有办法通过使用访问说明符来实现这一目标......?
编辑:我已经得到了一些有用的答案,但我认为我没有说清楚我的问题。只要ImplDataSource将doLoad()声明为protected或private,一切都很好。但是,仅查看AbstrDataSource,没有任何暗示doLoad()的任何实现应该是私有的(即使抽象的doLoad受到保护或私有,实际的实现也可以具有任何访问权限)。我想知道是否有可能以某种方式“强制”抽象doLoad()的任何实现是私有的。也许我只是想太复杂,最简单的方法是在抽象方法的文档中添加注释(“实现为私有或可能失败”)。答案 0 :(得分:1)
您要实现的目标称为模板方法模式和 我认为你在这里做的最好的事情就是委托doLoad方法减少“敏感”行为,并将loadData(以及你想要从派生类中隐藏的部分)置于私人访问中
答案 1 :(得分:0)
使方法doLoad()受到保护,然后只能从超类中调用它,并且它会重载(并隐藏)基类的纯虚方法。