如何"隐藏"虚拟方法? (C ++)

时间:2014-11-04 10:58:02

标签: c++ abstract

有一个标题非常相似的帖子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()的任何实现是私有的。也许我只是想太复杂,最简单的方法是在抽象方法的文档中添加注释(“实现为私有或可能失败”)。

2 个答案:

答案 0 :(得分:1)

您要实现的目标称为模板方法模式和 我认为你在这里做的最好的事情就是委托doLoad方法减少“敏感”行为,并将loadData(以及你想要从派生类中隐藏的部分)置于私人访问中

答案 1 :(得分:0)

使方法doLoad()受到保护,然后只能从超类中调用它,并且它会重载(并隐藏)基类的纯虚方法。