Note that there are some explanatory texts on larger screens.

plurals
  1. POC++ populating vectors inside class constructors
    primarykey
    data
    text
    <p>I have troubling addressing elements inside objects of Class3, please look at this simplified classes:</p> <pre><code>class Class1 { public: std::vector&lt;Class2&gt; c2v; Class1(); }; class Class2 { Class1 *instance; int id; public: std::vector&lt;Class3&gt; c3v; Class2 ( Class1 *instance, int id ); }; class Class3 { Class1 *instance; int id; public: Class3 ( Class1 *instance, int id ); }; </code></pre> <p>And their constructors:</p> <pre><code>Class1::Class1() { for ( int i = 0; i &lt; noi; ++i ) { c2v.push_back ( Class2 ( this, i ) ); } } Class2::Class2 ( Class1 *instance, int id ) { this-&gt;instance = instance; this-&gt;id = id; for ( int k = 0; k &lt; nok; ++k ) { c3v.push_back ( Class3 ( this-&gt;instance, k ) ); } } </code></pre> <p>In main() an object of Class1 is instantiated with its default constructor. Therefore it creates a vector c2v and fills it with 'noi' objects of Class2.</p> <p>At the same time, when the objects of Class2 are being put into c2v vector, they're instantiated and each one creates a vector c3v and fills it with 'non' objects of Class3.</p> <p>The code compiles fine but at runtime when accessing public attributes of Class2 from Class3 objects (via <code>this-&gt;instance-&gt;c2v[0].getSomeAttribute()</code>) the program stops with a EXC_BAD_ACCESS.</p> <p>Inspecting with a debugger shows that the pointer to <code>c2v[0]</code> gets corrupted (its value becomes 0x0).</p> <p>I'm a newbie of C++ I was wondering what is the error when trying to instantiate vectors this way. Should I only declare the vectors and populate them in a separate function called after the creation of all instances of Class2 and Class3 is finished?</p> <p>I'm adding some actual code, hope it won't be too long to read (please understand I've omitted some forward declarations and preprocessor directives):</p> <pre><code>// global variables extern char *filename; //not used extern int nodes; extern int numProdotti; extern int classe; //not used extern int maxNumRange; //not used extern int *numRanges; extern int *list ; extern int *typeProdMarket; extern int totalQtyDemand; //not used extern int totNumRanges; //not used extern struct product { int qty; int cost; } **prodMarket; extern struct range { int discount; int startOfRange; } **rangeMarket; //not used int main ( int argc, char *argv[] ) { Ctqd instance; instance.runOpt(); } class Ctqd { void greedySimple(); void greedySimpleReverse(); void greedyFromY(); void greedyByNiceness1(); void greedyByNiceness2(); void greedyByStepTier1(); void greedyByStepTier2(); void randomLocalSearch1(); void LocalSearch2opt(); public: std::vector&lt;Item&gt; items; std::vector&lt;Supplier&gt; suppliers; Solution *solution; Ctqd(); ~Ctqd(); void runOpt(); }; class Supplier { Ctqd *instance; int id; int refTotQty; int refDiscount; int refDiscountTier; double refTotPrice; double refUnitPrice; double niceness; int purTotQty; int purDiscount; int purDiscountTier; public: std::vector&lt;Offer&gt; offers; Supplier ( Ctqd *instance, int id ); int getId(); int getRefTotQty(); int getRefDiscount(); int getRefDiscountTier(); double getRefTotPrice(); double getRefUnitPrice(); double getNiceness(); int getPurTotQty(); int getPurDiscount(); int getPurDiscountTier(); void updateStats(); }; class Offer { Supplier *supplier; int id; int refQty; double refPrice; double niceness; int purQty; public: Offer ( Supplier *supplier, int id ); int getId(); int getRefQty(); double getRefPrice(); double getNiceness(); int getPurQty(); void setPurQty ( int qty ); int remainingQty(); }; Ctqd::Ctqd() { // constructing items vector for ( int k = 0; k &lt; numProdotti; ++k ) { items.push_back ( Item ( this, k ) ); } // constructing suppliers vector for ( int i = 0; i &lt; nodes; ++i ) { suppliers.push_back ( Supplier ( this, i ) ); } // building solution solution = new Solution ( this ); } Supplier::Supplier ( Ctqd *instance, int id ) { this-&gt;instance = instance; this-&gt;id = id; // computing total reference quantity refTotQty = 0; for ( int k = 0; k &lt; numProdotti ; ++k ) { refTotQty += std::min ( list[ k ] , prodMarket[ this-&gt;id ][ k ].qty ); } // computing reference discount coefficients refDiscount = 0; refDiscountTier = 0; for ( int r = 0; r &lt; numRanges[ this-&gt;id ]; ++r ) { if ( refTotQty &lt; rangeMarket[ this-&gt;id ][ r ].startOfRange ) { break; } else { refDiscount = rangeMarket[ this-&gt;id ][ r ].discount; refDiscountTier = r; } } //computing total reference price refTotPrice = 0; for ( int k = 0; k &lt; numProdotti ; ++k ) { refTotPrice += prodMarket[ this-&gt;id ][ k ].cost * std::min ( list[ k ] , prodMarket[ this-&gt;id ][ k ].qty ); } refTotPrice = refTotPrice * ( 1.000 - refDiscount / 100.000 ); //computing reference unit price refUnitPrice = refTotPrice / refTotQty; //computing supplier niceness niceness = refTotQty / refUnitPrice; purTotQty = 0; purDiscount = 0; purDiscountTier = 0; // building offers vector for ( int k = 0; k &lt; numProdotti; ++k ) { offers.push_back ( Offer ( this, k ) ); } } Offer::Offer ( Supplier *supplier, int id ) { this-&gt;supplier = supplier; this-&gt;id = id; // computing reference quantity refQty = std::min ( list[ this-&gt;id ] , prodMarket[ this-&gt;supplier-&gt;getId() ][ this-&gt;id ].qty ); // computing reference price refPrice = prodMarket[ this-&gt;supplier-&gt;getId() ][ this-&gt;id ].cost * ( 1.000 - this-&gt;supplier-&gt;getRefDiscount() / 100.000 ); // computing niceness of the offer niceness = refQty / ( ( prodMarket[ this-&gt;supplier-&gt;getId() ][ this-&gt;id ].cost + refPrice ) / 2 ); // init purQty to 0 purQty = 0; } </code></pre> <p>This is where I get the EXC_BAD_ACCESS:</p> <pre><code>int Offer::remainingQty() { return prodMarket[ supplier-&gt;getId() ][ id ].qty - purQty; } </code></pre> <p>I've done some experiments: Changed the vectors in the Ctqd class and in the Supplier class to vectors of pointer to objects. Problem was solved only partially. Still had a EXC_BAD_ACCESS when constructing the offers objects.</p> <p>The constructor for Offer class needs data from the Supplier object that created it. I thought that accessing that data while the suppliers vector was still being populated could lead to problems, so I created a little initialize() function in the supplier:</p> <pre><code>void Supplier::initialize() { // constructing offers vector for ( int k = 0; k &lt; numProdotti; ++k ) { offers.push_back ( new Offer ( this-&gt;instance, id, k ) ); } } </code></pre> <p>And added this at the end of the Ctqd class constructor:</p> <pre><code>// init newly built objects for ( int i = 0; i &lt; nodes; ++i ) { suppliers[i]-&gt;initialize(); } </code></pre> <p>Now things seem to be working fine. But i still didn't figure out what the problem exactly was.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload