The question may seem a little bit weird but I'll try to contestualize a little bit the use case.
Suppose you have a generic implementation of a two-dimensional (Cartesian) field with dimensions dim1 and dim2, coordinates c1 and c2.
struct Field2D {
struct size_type {
size_t dim1,dim2;
};
struct coordinates {
size_t c1,c2;
}
Field2D(size_type const & siz) : size_(siz), data(size_.dim1*size_.dim2) {}
double get(coordinates const & coords) {
return data_[coords.c1*size_.dim2 + coords.c2];
}
//Other methods
private:
size_type size_;
vector<double> data_;
};
You want to inherit from this class but you want to be more explicit about the nature of the coordinates. For example, a field PositionVersusTime whose coordinates are "x" and "t" and dimensions "nx" and "nt", whose usage I'd like to be
int main(){
PositionVersusTime::size_type siz;
siz.nx = 5;
siz.nt = 2;
PositionVersusTime myField(siz);
PositionVersusTime::coordinates coords;
coords.x = 2;
coords.t = 0;
auto out = myField.get(coords);
return 0;
}
The reason I want to do this is that the ordering may change depending on the field (for example a TimeVersusPosition) and sometimes "forgotten" by the user. Is there a way to obtain a similar behavior? or should I simply go with getters (e.g., coords.x() = 2) ?
The class whose members are inherited is called the base class, and the class that inherits those members is called the derived class. A derived class can have only one direct base class.
A class can always access its own (non-inherited) members. The public accesses the members of a class based on the access specifiers of the class it is accessing. A derived class accesses inherited members based on the access specifier inherited from the parent class.
It uses whatever access specifier it is defined under in the derived class. Therefore, a function that is defined as private in the base class can be redefined as public in the derived class, or vice-versa!
The child or derived class inherits all the features of its parent or base class, and is free to add features of its own.
No. You cannot "rename" a base class member in a derived class. That's simply not something the language allows.
A variable gets its name when it is declared and that is then its name forever. You can create aliases (references) to it if you like or you can have functions by whatever name that changes it, but the fundamental name of a variable is set in stone at declaration time.
Combining others solutions and using inheritance and reference data members, here is my solution.
Notice slight changes to the Field2D
variable types.
struct size_type{
size_t dim1, dim2;
};
struct PositionVsTime_size_type : public size_type{
size_t& nx = dim1;
size_t& nt = dim2;
};
struct coordinates {
size_t c1,c2;
};
struct PositionVsTime_coordinates : public coordinates{
size_t& x = c1;
size_t& t = c2;
};
struct Field2D {
Field2D(size_type& siz) : size_(siz), data_(size_.dim1*size_.dim2) {}
double get(coordinates& coords) {
return data_[coords.c1*size_.dim2 + coords.c2];
}
Field2D& set(coordinates& coords, double val){
data_[coords.c1*size_.dim2 + coords.c2] = val;
return *this;
}
private:
size_type& size_;
vector<double> data_;
};
struct PositionVersusTime : public Field2D {
PositionVersusTime(size_type& siz) : Field2D(siz) {}
};
int main(){
PositionVsTime_size_type siz;
siz.nx = 5;
siz.nt = 2;
PositionVersusTime myField(siz);
PositionVsTime_coordinates coords;
coords.x = 2;
coords.t = 0;
myField.set(coords, 5);
auto out = myField.get(coords);
cout << out << endl; // will print 5
return 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With