0

I am posting my code below as tested, with the respective outputs shown in comments after the "cout"-statements, and my QUESTIONS as to the output that I do not understand indicated by "--> WHY". I am completely at a loss and I apologize in advance for my assumed stupidity that appears to prevent me from understanding what is going on.

#include <experimental/filesystem>
#include <iostream>
#include <vector>

using namespace std;



struct S
{

struct BASE
{
static double testval;

virtual void set_testval(double val)    {testval = val;}
virtual double get_testval()            {return testval;}
};


template<typename T>
struct DerivedTemplate : public BASE
{
static double testval;

void set_testval(double val)    {testval = val;}
double get_testval()            {return testval;}
};


struct DERIVED_01 : DerivedTemplate<DERIVED_01>
{
//...
};

struct DERIVED_02 : DerivedTemplate<DERIVED_02>
{
//...
};

struct DERIVED_03 : DerivedTemplate<DERIVED_03>
{
//...
};


vector<unique_ptr<BASE> > DERIVED_TYPES;


S();

}; // END struct S


S::S()
{
    DERIVED_TYPES.resize(4);
}


double S::BASE::testval = 0;

template <typename T>
double S::DerivedTemplate<T>::testval = 1;


S s;


int main()
{

// Assign pointers to objects of derived structs to fields in vector of unique_ptr of base struct
{
unique_ptr<S::DERIVED_01> DERIVED (new S::DERIVED_01());
s.DERIVED_TYPES[0] = move(DERIVED);
}

{
unique_ptr<S::DERIVED_02> DERIVED (new S::DERIVED_02());
s.DERIVED_TYPES[1] = move(DERIVED);
}

{
unique_ptr<S::BASE> BASE (new S::BASE());
s.DERIVED_TYPES[2] = move(BASE);
}

{
unique_ptr<S::DERIVED_03> DERIVED (new S::DERIVED_03());
s.DERIVED_TYPES[3] = move(DERIVED);
}


cout << s.DERIVED_TYPES[0]->testval << endl;        // Output: 0
cout << s.DERIVED_TYPES[0]->get_testval() << endl;  // Output: 1  --> WHY is the output of this line "1" while that of the prior line was "0"?
                                                    // I assumed to be accessing the same member variable of the same object in both cases

cout << endl;

cout << s.DERIVED_TYPES[1]->testval << endl;        // Output: 0
cout << s.DERIVED_TYPES[1]->get_testval() << endl;  // Output: 1  --> WHY [same question]

cout << endl;

cout << s.DERIVED_TYPES[2]->testval << endl;        // Output: 0
cout << s.DERIVED_TYPES[2]->get_testval() << endl;  // Output: 0

cout << endl;

cout << s.DERIVED_TYPES[3]->testval << endl;        // Output: 0
cout << s.DERIVED_TYPES[3]->get_testval() << endl;  // Output: 1  --> WHY [same question]

cout << endl;


// Assign values to static member variables of derived struct objects
s.DERIVED_TYPES[0]->testval = 0.5;
s.DERIVED_TYPES[1]->testval = 1.5;
s.DERIVED_TYPES[2]->testval = 2.5;
s.DERIVED_TYPES[3]->testval = 2.75;


cout << s.DERIVED_TYPES[0]->testval << endl;            // Output: 2.75
cout << s.DERIVED_TYPES[1]->testval << endl;            // Output: 2.75
cout << s.DERIVED_TYPES[2]->testval << endl;            // Output: 2.75
cout << s.DERIVED_TYPES[3]->testval << endl;            // Output: 2.75  --> WHY are the outputs all "2.75"?

cout << endl;


s.DERIVED_TYPES[0]->set_testval(3.5);
s.DERIVED_TYPES[1]->set_testval(4.5);
s.DERIVED_TYPES[2]->set_testval(5.5);
s.DERIVED_TYPES[3]->set_testval(6.5);


cout << s.DERIVED_TYPES[0]->testval << endl;            // Output: 5.5
cout << s.DERIVED_TYPES[0]->get_testval() << endl;      // Output: 3.5

cout << endl;

cout << s.DERIVED_TYPES[1]->testval << endl;            // Output: 5.5
cout << s.DERIVED_TYPES[1]->get_testval() << endl;      // Output: 4.5

cout << endl;

cout << s.DERIVED_TYPES[2]->testval << endl;            // Output: 5.5
cout << s.DERIVED_TYPES[2]->get_testval() << endl;      // Output: 5.5

cout << endl;

cout << s.DERIVED_TYPES[3]->testval << endl;            // Output: 5.5
cout << s.DERIVED_TYPES[3]->get_testval() << endl;      // Output: 6.5

// Now, a "DIRECT ACCESS" of "testval" [s.DERIVED_TYPES[x]->testval]
// does not produce an output equal to the value assigned to 
// s.DERIVED_TYPES[3]->testval, the last one assigned, but an
// output equal to the one assigned to the pointer pointing to the
// one object of struct BASE instead of "DERIVED_..."
// --> WHY?


cin.get();

return 0;
}
Edmond
  • 1
  • 1
  • `s.DERIVED_TYPES[3]->testval = ...` always sets the single static `BASE::testval`. So the last assignment will be reported by *all* later direct reports of said same, regardless of derivation chain. Since slot-2 is a BASE instance, both direct assignment to `testval` and usage of `set_testval` will modify `BASE::testval`. None of the derivations do that. Their direct assignments modify `BASE::testval` (because you're using `BASE` pointers), but their `set_testval` virtual overrides modify their respective `DerivedTemplate::testval` . Step through your code in a debugger. you'll see it. – WhozCraig Jan 30 '21 at 11:22
  • Thank you for your comment! Yet I am still asking myself "why"? My assumption was that by moving the unique_ptr of type derived to a field in the vector that field would "assume" the type derived instead of base. Or put another way: Would there be any way to achieve what I am trying to achieve, namely to access memvars of derived types from a single container of pointers which I can loop through? I know I can use setter and getter functions and it works, but for my special purposes, it would be easier and less (coding) error prone to be able to access memvars directly. – Edmond Jan 30 '21 at 11:30
  • Not without casting, and that fundamentally breaks the reason for the chosen architecture in the first place. Stop accessing memvars directly and exclusively use virtual member functions instead. You can still invoke a base class virtual member (or non-virtual) directly. I.e. `s.DERIVED_TYPES[3]->BASE::get_testval()` if you really have to, but seriously think about whether you should/would or not. And clearly your warrant of "it would be... less error prone to be able to access memvars directly" doesn't hold water. were that true, you wouldn't be having the problem you are now. – WhozCraig Jan 30 '21 at 11:34
  • Thank you again. I guess you are right, not less error prone when being perfectly consequential, just a lot less work than having to write getters/setters for every single memvar in the struct template. Code looks more ... "clumsy"? But I take it from what you write that I have to bite this bullet for the advantage of effectively being able to loop through struct TYPES by using the unique_ptr vector, which I assign "dummy" obejcts to just to provide the checking logic. Another vector then holds the actual "working" objects. Any way I can sort of upvote your comment (not seeing this option)? – Edmond Jan 30 '21 at 11:53

0 Answers0