当容器在C ++中是const时,如何对容器持有的对象进行非const访问

时间:2013-01-10 01:47:08

标签: c++ pointers const-correctness

我有两个类之间的关系,以及下面示例中说明的一些其他功能代码。 MiddleMan类包含几个指向DataObject类实例的指针容器。我想在一个容器中强制执行对数据对象的只读访问,同时允许对另一个容器中的数据容器进行写访问。 MiddleMan的用户永远不能直接修改容器本身(ptr_vector成员)。

我想当通过DataObject const成员函数访问时,MiddleMan指针会发生const促销。我怎么能避免这个?在我的对象关系中,MiddleMan在逻辑上不拥有DataObject个实例。因此,我不希望DataObject实例受到const保护。

我已经使用了boost::ptr_vector容器,因为我理解STL容器对于这类事情可能更成问题。虽然没有解决我的问题。 我很高兴在MiddleMan中使用const_cast,但我不知道如何使用。

// const correctness access through middleman example
// g++ -I/Developer/boost  ptr_container_ex.cc
#include <boost/ptr_container/ptr_vector.hpp>

struct DataObject
{
    DataObject(size_t n) : _data(new float[n]) {}
    ~DataObject() {delete _data;}
    float * dataNonConst() { return _data; }
    const float * dataConst() const { return _data; }
    float * _data;
};


struct MiddleMan
{

    typedef boost::ptr_vector<DataObject> containerVec_t;

    const containerVec_t & inputVars() const { return _inputVars; }
    const containerVec_t & outputVars() const { return _outputVars; }

    void addInputVar(  DataObject * in  ) { _inputVars.push_back( in ); }
    void addOutputVar( DataObject * out ) { _outputVars.push_back( out ); }

    containerVec_t _inputVars, _outputVars;

};

// just an example that the DataObject instances are managed externally
DataObject g_dataInstances[] = {DataObject(1), DataObject(2), DataObject(3)};

MiddleMan theMiddleMan;


int main()
{
    theMiddleMan.addInputVar( &g_dataInstances[0]);  // this is just setup
    theMiddleMan.addOutputVar( &g_dataInstances[1]);

    const MiddleMan & mmRef = theMiddleMan; // I actually only have a const ref to work with

    // read data example
    const MiddleMan::containerVec_t & inputs = mmRef.inputVars();
    float read = inputs[0].dataConst()[0];

    // write data example
    const MiddleMan::containerVec_t & outputs = mmRef.outputVars();
    float * data_ptr = outputs[0].dataNonConst(); // COMPILER ERROR HERE:

    return 0;
}

我正在获取编译器输出:

ptr_container_ex.cc: In function ‘int main()’:
ptr_container_ex.cc:49: error: passing ‘const DataContainer’ as ‘this’ argument of ‘float* DataContainer::dataNonConst()’ discards qualifiers

2 个答案:

答案 0 :(得分:1)

您需要在每个不具有const访问权限的地方排除const修饰符:

containerVec_t & outputVars() { return _outputVars; } //Change definition in MiddleMan class

MiddleMan::containerVec_t & outputs = theMiddleMan.outputVars(); //Change reference type
float * data_ptr = outputs[0].dataNonConst(); //No compiler error here

答案 1 :(得分:-1)

一个工作方案使用const_cast访问outputVars。我无法返回对整个容器的引用,但是我可以获得返回开始和结束迭代器所需的功能。

// const correctness access through middleman example
// g++ -I/Developer/boost  ptr_container_ex.cc
#include <boost/ptr_container/ptr_vector.hpp>

struct DataObject
{
    DataObject(size_t n) : _data(new float[n]) {}
    ~DataObject() {delete _data;}
    float * dataNonConst() { return _data; }
    const float * dataConst() const { return _data; }
    float * _data;
};


struct MiddleMan
{
    typedef boost::ptr_vector<DataObject> containerVec_t;

    containerVec_t::iterator outputVarsBegin() const { return const_cast<containerVec_t&>(_outputVars).begin(); }
    containerVec_t::iterator outputVarsEnd() const { return const_cast<containerVec_t&>(_outputVars).end(); }

    const containerVec_t & inputVars() const { return _inputVars; }

    void addInputVar(  DataObject * in  ) { _inputVars.push_back( in ); }
    void addOutputVar( DataObject * out ) { _outputVars.push_back( out ); }

    containerVec_t _inputVars, _outputVars;

};

// just an example that the DataObject instances are managed externally
DataObject g_dataInstances[] = {DataObject(1), DataObject(2), DataObject(3)};

MiddleMan theMiddleMan;


int main()
{
    theMiddleMan.addInputVar( &g_dataInstances[0]);  // this is just setup
    theMiddleMan.addOutputVar( &g_dataInstances[1]);

    const MiddleMan & mmRef = theMiddleMan; // I actually only have a const ref to work with

    // read data example
    const MiddleMan::containerVec_t & inputs = mmRef.inputVars();
    float read = inputs[0].dataConst()[0];

    // write data example
    float * data_ptr2 = mmRef.outputVarsBegin()->dataNonConst(); // WORKS

    return 0;
}