/ / Как да имаме неконстроен достъп до обект, държан от контейнер, когато контейнерът се състои от C ++ - c ++, указатели, const-коректност

Как да имаме неконсултен достъп до обект, държан от контейнер, когато контейнерът се състои от C ++ - c ++, указатели, const-коректност

Имам връзка между два класа и допълнителен функционален код, илюстриран в примера по-долу. Най- MiddleMan клас държи няколко контейнера на указатели DataObject инстанции от клас. Искам да наложа достъп само за четене до обектите с данни в един контейнер, като същевременно позволявам достъп за писане до контейнерите за данни в другия. Потребителите на MiddleMan никога не трябва да могат да променят сами контейнерите директно ( ptr_vector членове).

Предполагам, че е налице промоция на DataObject указатели при достъп през MiddleMan const член функция. Как мога да избегна това? В моето обектно отношение, MiddleMan не е логично собственик на DataObject инстанции. По този начин не искам DataObject примери const-protected.

Използвал съм boost::ptr_vector контейнера, както разбирам, контейнерите за STL могат да бъдат по-проблематични за подобни неща. Не успях да разреша проблема си. Щастлив съм да използвам const_cast в MiddleMan, но не виждам как.

// 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

Отговори:

1 за отговор № 1

Трябва да изключите const modifiers на всяко място, в което няма да имате достъп до 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 за отговор № 2

Използва се един работен сценарий 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;
}