C++ difficulties accessing method from a deep inner class [closed] - c++

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I have several classes in my project and some of those classes are the members of other ones. While manipulating the outer class, I would like to access some parameters of its member classes (which could also have their own member classes).
I guess this is not exactly what are "nested classes" in C++, since nested class are being declared within the declaration of the outer class. Then the nested class may not be accessed from the outside of the outer class (just a piece of information for me, to make sure I don't write garbage).
Let’s say I have an AnalogSensor class (handles the behavior of a real analog sensor). This class may have several handlers (one for ADC requests handling, one for filtering incoming data, one for data handling, and the last one for deadzone management).
class LinearSpace {
public:
// Getters & setters
private:
uint16_t min_val; // I'm working with embedded devices
uint16_t max_val; // Those are values used for linear interpolations
// purposes
};
class DataHandler {
public:
// Some useful methods
uint8_t map_raw_data(); // Converts the mapped adc_result (10 bits)
// value into an 8-bit, interpolated value
private:
LinearSpace input_space; // Two values spaces used for interpolation
// purposes
LinearSpace output_space;
};
class AnalogSensor{
public:
// "High-Level" methods like void send_adc_request(void);
// which relies on the internal ADC hander
private :
AdcHandler adc_handler;
DataHandler data_handler;
Deadzone deadzone;
DataFilter data_filter;
};
Each one of those handlers may rely (or not) on other subclasses, like value ranges (minimum value, maximum value) which has its own getters and setters (getmin, getmax, setmin, and setmax).
Here is an example of what I could end with in my project:
AnalogSensor mysensor
|
- dataHandler data_handler
|
- LinearSpace input_space
| |
| - min_val
| |
| - max_val
|
- LinearSpace output_space
|
- min_val
|
- max_val
Well, now let’s say I want to modify the minimum and maximuml value of a given range, directly from the AnalogSensor class. How should I do?
This requirement comes from the necessity to adjust those values for each calibration process (at runtime), as voltages and electronic measurement may vary with time / external conditions such as moisture, etc.
I found many ideas on the Internet:
Declare a class as friend (AnalogSensor is the friend of
AdcHandler and dataFilter, etc...)
Declare as much getters and setters inside AnalogSensor which are dedicated to target one specific range (there will be tens of them and I think it is pretty dirty).
Or using pointers to access the exact valueRange I want to modify (without
breaking encapsulation I hope) directly from AnalogSensor class.
In this particular case, I can do something like this:
mysensor.getDataHandlerPointer()->getInputSpacePointer()->set_min(my_new_value);
How would you do to access those values?

If you have tens of ranges to change and monitor, it may be wise to store them in (an) array(s), and refer to the ranges by index. i.e.:
struct my_s
{
enum RangeSpace { input_space, output_space, N_SPACES };
void setRange(RangeSpace id, int min, int max) { spaces_[id].setMinMax(min, max); }
// etc...
private:
LinearSpace spaces_[N_SPACES];
};
Such indexing will optimize nicely when using constants when calling, as in:
//...
my_s s;
int a = 0, b = 0;
//...
s.setRange(my_s::input_space, a, b);

Related

why would you want a structure in a class? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
Have homework and we just went over classes. Thinking about how I could implement classes into my homework but the instructions say use a structure. (It's reading binary files and editing information) After looking at some stuff we did in class I probably don't need classes for my situation. But now I'm curious, why would you want to use a structure inside a class? Why would you use a structure when you can just set the data members in the class instead? What does struct have to offer to warrant doing this?
The primary benefit of putting values into an inner struct as opposed to just declaring them as member variables of the class would be that you can then instantiate multiple instances of that struct very easily, and refer to the set of variables in each struct with a single pointer or reference.
As an example, here are two implementations of a toy array-of-3D-points class. The first one just uses separate member-variables, while the second one declares an inner struct to represent a Point object.
Note that in the first implementation, the RotatePoint() method takes four arguments, while in the seconds argument it takes just two. Being able to refer to a Point with a single struct Point & argument (rather than three separate float & arguments) is both more efficient at run-time and less error-prone for the programmer to call.
// implementation without an inner struct
class MyPointArray1
{
public:
[...]
void RotatePoints(float radians)
{
for (int i=0; i<POINTS_ARRAY_LENGTH; i++)
{
// Hazard here -- a tired programmer might specify arguments in the wrong order!
RotatePoint(x[i], y[i], z[i], radians);
}
}
private:
enum {POINTS_ARRAY_LENGTH = 100};
float x[POINTS_ARRAY_LENGTH];
float y[POINTS_ARRAY_LENGTH];
float z[POINTS_ARRAY_LENGTH];
void RotatePoint(float & x, float & y, float & z, float radians)
{
// [math to update the values of x, y, and z would go here]
}
};
// implementation with an inner struct
class MyPointArray2
{
public:
[...]
void RotatePoints(float radians)
{
for (int i=0; i<POINTS_ARRAY_LENGTH; i++)
{
// It's pretty much impossible to get this wrong without provoking a compile-time error :)
RotatePoint(points[i], radians);
}
}
private:
enum {POINTS_ARRAY_LENGTH = 100};
struct Point
{
float x;
float y;
float z;
};
struct Point points[POINTS_ARRAY_LENGTH];
void RotatePoint(struct Point & pt, float radians)
{
// [math to update the values in (pt) would go here]
}
};
From my understanding, you would implement a struct inside a class when you want to create objects within that class only. Outside of the class, you would not be able to create objects of that struct.

Decouple visualization methods and application [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
this is my first question on SO, so please bear with me.
We develop an application, which gathers data, and we have methods that let us visualize the data in various ways. With growing number of methods, we decided to separate the application and the visualization methods. I'm wondering what is the best way to accomplish this. I've come up with the following code, which somewhat tries to separate the two, but still ...
Is there a better way to do it?
// forward declaration
class App;
// Interface to all visualization methods
struct Methods {
virtual void show(App * a) = 0;
};
// Some visualization method
struct Method0 : public Methods {
void show(App * a) {
a->getData();
}
};
class App {
public:
vector<Methods *> methods;
void run() {
// draw all registered methods
for (auto m : methods)
m->show(this);
}
int getData() {
// parse and precompute data (time-consuming, thus do it only once)
// return the required data (not just an int..)
return 42;
}
};
void main() {
App a;
// register some methods
a.methods.push_back(new Method0());
// run the application
a.run();
// clean up
for (auto m : a.methods) delete(m);
}
EDIT
I think Alexander and Petr pointed me in the correct direction, thank you. I'll follow Petr's suggestion and try to separate the data into another class.
Addressing the comment by Spektre:
Developed on Windows (MSVC), otherwise platform independent.
The visualization is mostly static and changes based on user input. I guess 10 updates per second is an upper bound on the refresh rate.
What do you mean by data transfer times?
Memory is not an issue.
The data is a bunch of vectors of objects holding other vectors of objects, 5 dimensions in total.
One visualization is similar to ROC curve, containing several curves, so we need to traverse part/all the dimensions and compute some statistics. The result is shown in the following figure.
What you have there already looks quite good. As you have probably already assumed, you are not the first person to have this kind of problem. The standard solution for the separation of your data from your visualization is known as the Model View Controller Pattern (MVC), which not only decouples the presentation of your data from the data itself, but also allows for simple manipulation of the data from the display.
If you just want to display your data, then you might want to have a look at the Observer Pattern. Then again, what you have is already quite close to this pattern.
In addition to an answer by Alexander, I will mention that actually you did not completely separated data and visualization. The Application class still knows both about the internal structure of data and about the vector of visualization methods. What you should better do is to have a separate class, say Data, the will be doing all the computations you need, and then have the main class (App for example) that will just handle registration of methods and passing data to them.
Something like
class Data;
struct Methods {
virtual void show(Data * a) = 0;
};
struct Method0 : public Methods {
void show(Data * d) {
d->getData();
}
};
class Data {
public:
int getData() {
// parse and precompute data (time-consuming, thus do it only once)
// return the required data (not just an int..)
return 42;
}
}
class App {
public:
vector<Methods *> methods;
Data* data;
void run() {
// draw all registered methods
for (auto m : methods)
m->show(data);
}
};

Is there anyway in c++ to make a function of a class who's objects each do something different for that function? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Just some background:
I am making a monopoly game and now I have to implement the actions of each space such as GO, properties (upgrading), chance, community chest, jail, etc.
I've considered making a different class for each space (but obviously that would be very time consuming). I believe there is also a way do to it with inheritance and pure virtual functions. Any way you guys can think that would make this a simpler process?
Thanks!
There are only a few different types of spaces:
properties
railroads
chance / community chest
utilities
other single ones like go, jail, parking, tax
For example you could have a Property class where each instance of the class has a different name/colour/price. You wouldn't have to make 22 different classes, just have 22 instances of the same class with different names.
Note that having class instances that represent spaces you can land on is only one way to implement a game like that. I'm pretty sure I wouldn't choose that option.
There are two ways you can make a function do different things given an object:
Differentiate the behavior based on the data of the object.
You could capture the differences in the various spaces using data.
enum SpaceType
{
GO, CHANCE, COMMUNITY_CHEST, // etc...
};
class Space
{
public:
void foo()
{
switch (spaceType)
{
case GO:
// DO stuff for GO
break;
case CHANCE:
// DO stuff for CHANCE
break;
// etc..
}
}
private:
SpaceType spaceType;
}
Differentiate the behavior based on the type of an object.
class Space
{
public:
virtual void foo() = 0;
};
class GoSpace : public Space
{
public:
virtual void foo()
{
// Do stuff for GO
}
};
class ChanceSpace : public Space
{
public:
virtual void foo()
{
// Do stuff for CHANCE
}
};
// Similarly for other classes.
Pick your method. Personally, I would pick the second method because the logic for each different type is put into their own functions, without the complications of what other types do.

Differentiating between data class and logic class in agile [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
I've been reading an agile book about clean coding, mainly in Java and c#. Considering the concept of differentiating between a data class and a logic/object class. I have the following situation in c++, where I can't decide which variant is a clean code. I have a Plane class with some attributes and these attributes change when only one of them changes, so
First Method
class Plane3D {
public:
BBox bbox;
float l,w,h;
void setbbox(BBox bbox) {
this->bbox = bbox;
recalculateLWH();
}
void setLWH(float l, float w, float h) {
//set here
recalculateBBOX();
}
};
This makes sense to me, since to the user he is just calling one method and doesn't have to care about internal work of the class. but this is a violation for a data class, that it contains logic
Now the
Second method
class Plane3D {
public:
BBox bbox;
float l,w,h;
void setbbox(BBox bbox) {
this->bbox = bbox;
}
void setLWH(float l, float w, float h) {
//set here LWH
}
};
int main() {
BBox bbox;//init here
Plane plane;
plane.setBBox(bbox);
recalculateLWH(plane);
}
Now the second method actually separates the data class from the implementation but it increases the responsibilities of the class user and forces him to make an extra call. To my understanding the second method is the correct one from an agile POV, but I find the first method more logical to use.
I'd like to know which of the two methods would make more sense for you guys to undertsand and use
Regards
In this case I think you should prefer first method to second.
Your method calls should transform object from one correct state to another correct state. Using the second method after your setBBox(bbox); call your object moves to some incorrect state indeed.
But 'logic class way' can however take place in another situation.
Consider you should move plane:) from hangar to landing strip. Now it will be naturally to introduce new class named Tractor and use it like tractor.move(plane)

Is it better to store class constants in data members or in methods?

I recently wrote a class that renders B-spline curves. These curves are defined by a number of control points. Originally, I had intended to use eight control points, so I added a constant to the class, like so:
class Curve
{
public:
static const int CONTROL_POINT_COUNT = 8;
};
Now I want to extend this class to allow an arbitrary amount of control points. So I want to change this to:
class Curve
{
public:
int getControlPointCount() {return _controlPointCount;}
};
The question is whether it isn't better to store constants in methods to begin with, to facilitate adaptability. In other words, isn't it better to have started thus:
class Curve
{
public:
int getControlPointCount() {return 8;}
};
The advantage of this is that I could have just changed one symbol in the method in question, instead of moving around constants etc.
Is this a good practice or a bad one?
int getControlPointCount() {return _controlPointCount;}
This is an accessor. Swapping a const static for an accessor is not really a gain as litb has pointed out. What you really need to future-proof is probably a pair of accessor and mutator.
int getControlPointCount() {return _controlPointCount;} // accessor
I'd also throw in a design-const for the accessor and make it:
int getControlPointCount() const {return _controlPointCount;} // accessor
and the corresponding:
void setControlPointCount(int cpc) { _controlPointCount = cpc;} //mutator
Now, the big difference with a static object is that the control-point count is no longer a class-level attribute but an instance level one. This is a design change. Do you want it this way?
Nit: Your class level static count is public and hence does not need an accessor.
Typically I favour maintaining as few couplings manually as possible.
The number of control points in the curve is, well, the number of control points in the curve. It's not an independent variable that can be set at will.
So I usually would expose a const standard container reference:
class Curve
{
private:
std::vector<Point>& _controlPoints;
public:
Curve ( const std::vector<Point>& controlPoints) : _controlPoints(controlPoints)
{
}
const std::vector<Point>& getControlPoints ()
{
return _controlPoints;
}
};
And if you want to know how many control points, then use curve.getControlPoints().size(). I'd suspect that in most of the use cases you'd want the points as well as the count anyway, and by exposing a standard container you can use the standard library's iterator idioms and built-in algorithms, rather getting the count and calling a function like getControlPointWithIndex in a loop.
If there really is nothing else in the curve class, I might even go as far as:
typedef std::vector<Point> Curve;
(often a curve won't render itself, as a renderer class can have details about the rendering pipeline, leaving a curve as purely the geometric artifact)
To better answer your question, one should also know how the controlPointCount variable is set. Is it set outside from your class? In this case, you should also define a setter. Or the Curve class is the sole responsible for setting it? Is it set only on compile time or also on runtime.
Anyway, avoid a magic number even in this form:
int getControlPointCount() {return 8;}
This is better:
int getControlPointCount() {return CONTROL_POINT_COUNT;}
A method has the advantage that you can modify the internal implementation (use a constant value, read from a configuration file, alter the value dynamically), without affecting the external of the class.
class Curve
{
private:
int _controlPointCount;
void setControlPointCount(int cpc_arg)
{
_controlPointCount = cpc_arg;
}
public:
curve()
{
_controlPointCount = 8;
}
int getControlPointCount() const
{
return _controlPointCount;
}
};
I will create a code like this, with set function in private, so that no body can play with control point count, until we move to the next phase of development..where we update start to update the control point count at runtime. at that time, we can move this set method from private to public scope.
While understanding the question, I have a number of conceptual problems with the example:
What is the return value for getControlPointCount() when the number of control points is not limited?
Is it MAXINT?
Is it the current number of control points on the curve (thus breaking the logic that says that this is the largest possible number of points?)
What happens when you actually attempt to create a curve with MAXINT points? You will run out of memory eventually.
The interface itself seems problematic to me. Like other standard collection classes, the class should have encapsulated its limitation on number of points, and its AddControlPoint() should have returned an error if a limitation on size, memory, or any other violation has occurred.
As for the specific answer, I agree with kgiannakakis: a member function allows more flexibility.
I tend to use configuration + constant (default value) for all 'stable' values through the execution of the program. With plain constants for values that cannot change (360 degrees -> 2 pi radians, 60 seconds -> 1 minute) or whose change would break the running code (minimum/maximum values for algorithms that make them unstable).
You are dealing with some different design issues. First you must know whether the number of control points is a class or instance level value. Then whether it is a constant at any of the two levels.
If all curves must share the same number of control points in your application then it is a class level (static) value. If different curves can have different number of control points then it is not a class level value, but rather a instance level one.
In this case, if the number of control points will be constant during the whole life of the curve then it is a instance level constant, if it can change then it is not constant at this level either.
// Assuming that different curves can have different
// number of control points, but that the value cannot
// change dynamically for a curve.
class Curve
{
public:
explicit Curve( int control_points )
: control_points_( control_points )
{}
// ...
private:
const int control_points_;
};
namespace constant
{
const int spline_control_points = 8;
}
class Config
{
public:
Config();
void readFile( std::string const & file );
// returns the configured value for SplineControlPoints or
// constant::spline_control_points if the option does not
// appear in config.
int getSplineControlPoints() const;
};
int main()
{
Config config;
config.readFile( "~/.configuration" ); // read config
Curve c( config.getSplineControlPoints() );
}
For integral type I'm usualy using:
class Curve
{
public:
enum
{
CONTROL_POINT_COUNT = 8
};
};
If constant doesn't need for any entities except class implementation I declare constants in *.cpp file.
namespace
{
const int CONTROL_POINT_COUNT = 8;
}
In general, all your data should be private and accessed via getters and setters. Otherwise you violate encapsulation. Namely, if you expose the underlying data you lock yourself and your class into a particular representation of that underlying data.
In this specific case I would have done the something like the following I think:
class Curve
{
protected:
int getControlPointCount() {return _controlPointCount;}
int setControlPointCount(int c) { _controlPointCount = c; }
private:
static int _controlPointCount = 0;
};
Constants in general should not be defined inside methods. The example you're choosing has two unique features. First, it's a getter; second, the type being returned is an int. But the point of defining constants is to use them more than once, and to be able to refer to them in a convenient way. Typing "8" as opposed to "controlPointCount" may save you time, and may not seem to incur a maintenance cost, but this won't typically be true if you always define constants inside methods.