Changing old code which is difficult to understand - c++

My main trouble comes from void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));, t.sparsity(p, _decay), and the "SparsityTemplate" of which there are more than one kind. I either get the header definition to compile and not the code or vice-versa. How should these definitions be properly setup?
The example below does not compile but demonstrates what I am struggling with. I would like to have 2 or more different SparsityTemplates and properly use const and private variables. Initialization was missing and I attempted to add that. The sample takes code from a linear algebra library, so namespaces have been removed.
_Ws as does _t comes from a linear algebra namespace
#include <cmath>
#include "matrix.h"
/**
* Sparsity template with exponential increase depending on the time
* index p.
*/
class Deconvolver
{
class SparsityTemplate
{
public:
virtual double sparsity(double p) const;
virtual ~SparsityTemplate() = default;
};
class ExponentialSparsityTemplate: public SparsityTemplate
{
public:
ExponentialSparsityTemplate(double sparsity, double sparsityexp) :
_sparsity(sparsity), _decay(sparsityexp) {}
virtual ~ExponentialSparsityTemplate() = default;
void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));
private:
double _sparsity = 0;
double _decay = 0;
};
void setWSparsity(const ExponentialSparsityTemplate(& t)(double wSparsity, double SparsityExp));
};
int main()
{
double wSparsity = 0.01;
double wSparsityExp = 1.7;
// The Matrix is 10 x 5 and is filled by a generator function
Matrix x(10, 5, );
Deconvolver d(x, 10, 3);
d.setWSparsity(
ExponentialSparsityTemplate(wSparsity, wSparsityExp));
}
void Deconvolver::setWSparsity(
const ExponentialSparsityTemplate(& t)(double wSparsity, double wSparsityExp))
{
_sparsity = wSparsity * std::pow(sparsityexp, p);
for (unsigned int p = 0; p < _t; ++p)
{
for (unsigned int j = 0; j < _wS[p]->cols(); ++j)
{
for (unsigned int i = 0; i < _wS[p]->rows(); ++i)
_wS[p]->at(i, j) = t.sparsity(p, _decay);
}
}
}

The problem was a combination of things:
C++ Virtual function being hidden
https://www.learncpp.com/cpp-tutorial/constructors-and-initialization-of-derived-classes/
In my project some virtual functions had used the same name as those in the initialization list and as I was trying to initialize and remove unused variables, I had disturbed hidden virtual functions which I hadn't fully understood. The exact same names being used made the code very difficult to follow so I went back to the original code and more slowly applied name changes to private variables and member initialization lists, and then made changes to virtual functions. I used () not {} for parameters in point 2 but the example was helpful as the same name was not used.

Related

How to read data in private members of the class in main.cpp file?

I have a trouble with usage of private members of the class! I try to read and remember data into them in main.cpp file. I don't need to create any other values to remember read data. How to fix this problem and use them? I use <fstream> library to read data from file and remove them into ofstream file for output. I use .h files and .cpp files and main.cpp file.
Here is code in matrix.h file:
class Matrix
{
private:
int R; // amount of rows
int C; // amount of columns
double **mat; // pointer to two-dimensional array
public:
Matrix(); // default constructor
Matrix(Matrix &&) // move constructor
Matrix(int, int); // constructor with two parameters
double &ReturnReferenceToElement(int, int); // method to return reference to element of array
}
This is matrix.cpp file:
#include <iostream>
#include "matrix.h"
Matrix::Matrix()
{
R = 3;
C = 3;
mat = new double *[R];
for(int i = 0; i < R; i++)
{
mat[i] = new double [C];
}
}
Matrix::Matrix(Matrix &&M)
{
R = M.R;
C = M.C;
for(int i = 0; i < R; i++)
{
for(int j = 0; j < C; j++)
{
mat[i][j] = M.mat[i][j];
}
}
}
main.cpp:
#include <iostream>
#include <fstream>
#include "matrix.h"
using namespace std;
int main()
{
Matrix m;
ifstream in("in.txt");
ofstream out("out.txt");
in >> R >> C; // here I try to read data from file into private member
for(int k = 0; k < R; k++)
{
for(int s = 0; s < R; s++)
{
in >> mat[k][s]; // here I try to read into the private member
}
}
out << SumOfElements(**mat, R, C);
out << Averaged_Matrix(**mat, R, C);
return 0;
}
Functions SumOfElements() and Averaged_Matrix() are written in another file which is connected, and they work correctly.
Is it possible to use private members without setters and getters?
You're not allowed to access private fields from outside the containing class. But it looks like you have a constructor that takes R and C -- so read those fields then construct a Matrix object, passing R and C as arguments.
The idea of private methods is that you very specifically aren't supposed to touch them. So you can either add getters and setters, or you can reframe how you're trying to do what you're trying to do.
int r, c;
cin >> r >> c;
Matrix m(r, c);
If you ever feel the need to access private members of a class, then there's something terribly wrong. Either with the classes design, or in the way you want to interact with it.
In your particular case, the class design itself is ill conceived. In particular the problem attempted to be masked by declaring certain members private is, that altering them after construction will corrupt the classes behavior.
Your approach to this makes this is a XY problem: You think that you have to somehow deal with the access specifier, when in fact, the non-constness of members of the class that must not be altered is the cause of your troubles.
BTW: double **mat; does not make a 2D array. It makes an (1D) array of pointers to (1D) arrays of doubles. The two level indirection upon access will kill performance, not to speak of the high likelyhod that rows/columns of the matrix won't be contiguous in memory and thus will perform poorly due to cache misses and it being hard to prefetch.
A much better design for you class would look like this
#include <cstddef>
#include <cmath>
class Matrix
{
public:
typedef unsigned short dim_t;
dim_t const R; // amount of rows
dim_t const C; // amount of columns
double *const mat; // pointer to two-dimensional array
// NO DEFAULT CONSTRUCTOR!
// copy constructor
Matrix(Matrix const &m)
: R(m.R), C(m.R)
, mat(new double[(size_t)R * (size_t)C])
{
auto const N = (size_t)R * (size_t)C;
for(size_t i = 0; i < N; ++i){ mat[i] = m.mat[i]; }
}
// constructor with two parameters
Matrix(dim_t const r_, dim_t const c_)
: R(r_), C(c_)
, mat(new double[(size_t)R * (size_t)C])
{
auto const N = (size_t)R * (size_t)C;
for(size_t i = 0; i < N; ++i){ mat[i] = NAN; }
}
~Matrix(){ delete[] mat; }
// methods to return reference to element of
// !!! THOSE DO NOT PERFORM BOUNDS CHECKS!
double &operator()(dim_t const r, dim_t const c)
{ return mat[(size_t)R*(size_t)c + (size_t)r]; }
double const &operator()(dim_t const r, dim_t const c) const
{ return mat[(size_t)R*(size_t)c + (size_t)r]; }
};
Why is this better? First and foremost, by being declared const members of the struct, the need to "hide" them from the outside, that is protecting them from unintended alteration is gone; if one really want to be so hard pressed to alter those elements it can be done by forcing the compiler into undefined behavior, but the same methods would also allow to discard the access specifiers.
Thus where you feel the need to directly access elements of Matrix::mat you can do so, in relative safety. The compiler will forbid you to alter the
Now you might wonder why I declared a type for the dimensions that is unsigned short. The reason for this is, that on most relevant architectures and platforms out there (except 8 and 16 bit microcontrollers), the result of multiplication of the short will always fit into a size_t, so this prevents running into an integer overflow bug on allocation of the 2D array.
You can then use that like this:
#include <iostream>
#include <fstream>
#include "matrix.h"
int main()
{
std::ifstream in("in.txt");
Matrix::dim_t R, C;
in >> R >> C;
Matrix m(R,C);
for( Matrix::dim_t k = 0; k < m.R; k++ )
for( Matrix::dim_t s = 0; s < m.C; s++ ){
in >> m(k, s);
}
std::ofstream out("out.txt");
out << SumOfElements(m.mat, m.R, m.C);
out << Averaged_Matrix(m.mat, m.R, m.C);
return 0;
}

Create a function in the memory to call it later

Ok, my question is probably stupid, but I will regreat not asking it.
I would like to know if it is possible to create a function during program execution and then be able to call it later. This function will not be hard coded because it depends on many initial parameters decided by the program user. The objective would be to avoid calling these parameters, each time we need to call this function and hence, gain execution time and memory. I will give a minimalist example because I believe my question is not so easy to understand just with words.
In this example, I have a class Parameters that contain parameters A1, A2, A3 used to solve an equation. These parameters vary due to initial conditions. The second class CalculFunction uses these Parameters to solve the equation at the moment t. The way it is coded, each time I have to evaluate a new moment t', I have to go through the Parameters objects again to solve the equation. However, I would like to store directly a function in the memory, that contains the correct parameters and can be evaluated at t1, t2 etc.. without requiring to call startCalculation(const double & t, const double & initValue) method again.
My goal is to construct the function only one time and have in the memory a function f[i] = initValue * sum( A1[i][j] / A2[i][j] * exp( -A3[i] * t) where the sum occurs on j. Hence, I just call fi to get results without reconstructing the whole loops on j.
class Parameters
{
public:
Parameters();
QVector<double> & getA1(){return m_a1;};
QVector<double> & getA2(){return m_a2;};
double & getA3(){return m_a3;};
private:
QVector<double> m_a1;
QVector<double> m_a2;
double m_a3;
};
class CalculFunction
{
public:
CalculFunction(const QVector<Parameters> & allParam): m_parameters(allParam);
void startCalculation(const double & t, const double & initValue)
{
for(int i = 0; i < m_parameters.size(); i++)
{
m_results.append(0.);
for(int j = 0; j < m_parameters[i].getA1().size(); j++)
{
m_results[i] += m_parameters[i].getA1()[j] / m_parameters[i].getA2()[j] * exp(- (m_parameters[i].getA3() ) * t );
}
m_results[i] *= initValue;
}
}
private:
QVector<Parameters> m_parameters;
QVector<double> m_results;
};
You are looking for functor then. Functor is a class that is capable to storing internal states but has the operator() member that acts like a function.
class AFunc
{
public:
AFunc(A1 a1, A2 a2, A3 a3) : a1(a1), a2(a2), a3(a3) {}
T operator()(arguments ...) {
T t
...
return t;
}
private:
A1 a1;
A2 a2;
A3 a3;
};
where T is the return type.
You can have as many arguments in the constructor and operator(...) as you need.
You would just call it like
AFunc af(a1, a2, a3);
T t = af(arguments ...);
in your code.
I would re-envision your Parameters class. At the moment, it is a glorified struct, some data with getters, but no logic. Instead of simply storing the parameters, you could view it as your function. Put the logic of how to calculate a value at a particular time in this class. If you want it to look like a function call, you can use operator(), but you could also use a named member function, perhaps eval(). Let's go with the operator for now.
class Function // Not the best name, but good enough for now.
{
public:
Function(QVector<double> param1, QVector<double> param2, double param3) :
m_a1(std::move(param1)),
m_a2(std::move(param2)),
m_a3(param3)
{}
// This is what will evaluate your function at a given time. This will not
// speed up the execution, but it does help improve data encapsulation.
double operator()(double t)
{
double result = 0.0;
for(int j = 0; j < m_a1.size(); j++)
{
result += m_a1[j] / m_a2()[j] * exp(- m_a3 * t );
}
return result;
}
private:
const QVector<double> m_a1; // Add `const` to these if you want to
const QVector<double> m_a2; // emphasize that they do not change
const double m_a3; // after initialization.
};
All that's happened is some logic got shifted into this class. There is no expected savings in execution time. The savings comes when you try to write your other class.
class CalculFunction
{
public:
CalculFunction(const QVector<Function> & allParam): m_parameters(allParam) {}
void startCalculation(const double & t, const double & initValue)
{
for(int i = 0; i < m_parameters.size(); i++)
m_results.append(m_parameters[i](t) * initValue); // Invoke operator() here
}
private:
QVector<Function> m_parameters;
QVector<double> m_results;
};
The overall code is shorter and more organized, optimizing the programmer's time.

Problem passing function pointer to a class c++

I'm trying to implement a numerical ODE solver in c++ but I'm having troubles with function pointers (I'm still trying to understand how they works inside classes).
I have a parent class (ODEint) and subclasses in which I will implement different possible algorithms to solve an equation. I pass a function pointer to the parent class (the function represents the equation which is independent of the solver) but I need that function in the child class (different solvers threat that equation in different ways).
When I call the function via pointer in the child class I get the error
odeint.cpp:38:13: error: ‘((Euler*)this)->Euler::.ODEint::field’ cannot be used
as a member pointer, since it is of type ‘pfunc {aka std::vector ()(double)}’
(this->*field)(y);
Here are classes definitions
typedef vector<double> (*pfunc)(double*);
class ODEint {
protected:
double h;
int neq;
double* init_cond;
int nsteps;
string method;
vector<vector<double>> y;
pfunc field;
public:
ODEint(int neq, int nsteps, pfunc);
void setInitCond(double* init_cond);
void solveEq();
virtual vector<double> advance(double h, double *y);
};
class Euler: public ODEint {
public:
Euler(int neq, int nsteps, pfunc, double h);
vector<double> advance(double h, double *y);
};
And here is part of the classes implementation
ODEint::ODEint(int neq, int nsteps, pfunc field){
this->neq = neq;
this->nsteps = nsteps;
this->y.resize(nsteps);
this->field = field;
for (int i = 0; i < nsteps; i++){
this->y[i].resize(neq);
}
}
Euler::Euler(int neq, int nsteps, pfunc field, double h) : ODEint(neq, nsteps, field){
this->h = h;
}
void ODEint::solveEq(){
int n;
cout << "Strarting solver..." << endl;
vector<double> x;
for (n = 0; n < this->nsteps; n++){
x = y[n];
y[n+1] = this->advance(this->h, &x[0]);
}
cout << "Solution termined. Nsteps: " << n << endl;
}
vector<double> Euler::advance(double h, double *y){
vector<double> ynext; ynext.resize(this->neq);
vector<double> f; f.resize(this->neq);
(this->*field)(y); <---------------------------------------------- here is the problem
for (int i = 0; i < this->neq; i++){
ynext[i] = y[i] + h*f[i];
}
}
Finally here is the main
vector<double> field(double *y){
vector<double> vf;
vf[0] = -y[0];
vf[1] = -y[1];
return vf;
}
int main(){
double init_cond[2] = {1.0, 2.0};
const int neq = 1;
Euler prova(neq, (int)1e4, field, 1e-4);
prova.setInitCond(&init_cond[0]);
prova.solveEq();
return 0;
}
I know there may be other problems but I'm still learning c++ and actually the priority is to understand the reason of this error.
Thank you in advance and sorry if the code is a bit confused but as I said previously I'm a kind of beginner.
Your example is a bit large, I didn't use it as-is. But I can spot a fix, with a smaller repro: (I kept your style)
#include <vector>
typedef std::vector<double> (*pfunc)(double*);
class Foo
{
public:
pfunc field;
};
std::vector<double> Bar(double*)
{
return std::vector<double>{};
}
int main()
{
Foo f;
double x;
f.field = &Bar;
(&f)->field(&x);
}
The only meaningful change I needed is to remove the * in front of the call to field().
Now, I will advise not using this pattern at all. The OOP way, IMO would be way cleaner here:
class BaseODE
{
public:
virtual std::vector<double> field(double*) = 0;
// put the rest of the code here.
// when field is called, the Euler version will be called.
};
class Euler:public BaseODE
{
public:
virtual std::vector<double> field(double*) override;
};
Basically, you have no need yet for function pointers, lambdas, std::function or anything complex.

initialize array in constructor

I want to have a class which has a member array. The size of the array should be given when I initialize the object. I just found a way with pointers to do this. I think it is working correctly, but can you maybe tell me if this is the best way to do it or if there are any things which do not work which I haven't recognized yet?
#include <iostream>
using namespace std;
class Surface {
private:
float dx;
int N;
float* mesh_points;
public:
Surface(float, int);
~Surface();
void set_dx (float);
float get_dx();
};
Surface::Surface(float dx,int N){
this->dx = dx;
this ->N = N;
mesh_points = new float[N];
}
void Surface::set_dx (float dx) {
this->dx = dx;
}
float Surface::get_dx (void) {
return dx;
}
Surface::~Surface(){
delete[] mesh_points;
}
int main () {
Surface s(1.2,10);
s.set_dx (3.3);
cout << "dx: "<< s.get_dx() <<endl;
float mesh_points[3];
return 0;
}
can you maybe tell me if this is the best way to do it or if there are any things which do not work which I haven't recognized yet?
That'd be my take basing on existing best practices:
class Surface {
private:
std::vector<float> mesh_points;
public:
float dx;
Surface(float dx, std::size_t n);
};
Surface::Surface(float dx, std::size_t n)
: dx(dx)
, mesh_points(n)
{
}
In short, the changes made:
Got rid of manual memory management, which implies dtor as well.
Added names for parameters in declarations (really important for usability/IDEs, don't remove them!)
Got rid of superfluous accessors and made dx public.
Used ctor init lists, making the body obsolete.
Got rid of using namespace std; in lieu of explicit std:: prefix.
Changed n type to std::size_t (see comment).
Please note that the current interface doesn't allow any access to mesh_points.
Here's an alternative suggestion that allows you to keep your current implementation but is a lot safer.
class Surface {
private:
float dx;
int N;
float* mesh_points;
public:
Surface(float, int);
~Surface();
void set_dx (float);
float get_dx();
Surface(const Surface&) = delete; // new
Surface& operator=(const Surface&) = delete; // new
};
By deleting the implementation of the copy constructor and copy assignment operator you prevent your Surface objects from being copied (which would likely crash your program anyway). Any attempt to copy Surface objects will now result in a compile time error.
Only a suggestion, my first choice would always be to use std::vector.

C++ Using member functions from a similar virtual public class

Suppose I have a bunch of inherited classes like this:
...and they all serve the purpose of making all sorts of polynomials. Class X is mainly a variable tank, classes A, B, etc are all virtual public X and each creates ont type of polynomial, class Y makes the calls. Besides A and B, any other class can be added.
Now, everything works but for a newly added "virtual public" class I need to reuse some member function(s) from other classes, here from A inside class B. I tried to make the simplest example:
#include <iostream>
#include <cmath>
#include <functional>
// variable tank
class X
{
protected:
// general variables
double *m_c;
int m_n;
double m_w;
// funcX related
double m_r;
int m_i {0};
public:
~X() = default;
/* Simple bracketed root-finding. This is called from more than
* one "virtual public" classes.
*/
const double funcX(const double &x, const double &y, \
std::function<const double(const double&, const int&)> fp, \
const int &k)
{
double a {x}, b {y}, fmid;
while (m_i<100)
{
m_r = 0.5*(a + b);
fmid = fp(m_r, k);
if (fabs(b-a) <= 1e-3)
break;
if (fmid < 0)
b = m_r;
else
a = m_r;
++m_i;
}
return m_r;
}
};
// one of the many classes that generate polynomials
class A: virtual public X
{
public:
void funcA(const int &n)
{
// set order
m_n = n;
// calculate X::m_c[i]
m_c = new double[m_n+1];
for (short i=0; i<=m_n>>1; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i<<1] = sgn/((i + 1.0)*(i + 1.0));
}
// The polynomial is zero somewhere, use funcX() to find where.
m_w = funcX(5.0, 0.0, \
[this](const double &x, const int &n) \
{ return calcA(x, n); }, \
m_n);
}
// calculates the value of the polynomial of order n, at x
const double calcA(const double &x, const int &n) const
{
double out {static_cast<double>(m_c[0])};
for (short i=1; i<=n; ++i)
out = m_c[i] + x*out;
return out;
}
};
class B: virtual public X
{
private:
A m_a; // otherwise the lambda function does not "catch" it
public:
void funcB(const int &n)
{
// same as in A
m_n = n;
// same as in A, calculate coefficients
m_c = new double[m_n+1];
for (short i=0; i<=m_n; ++i)
{
int sgn {i%2 ? -1 : 1};
m_c[i] = sgn/((i + 1)<<1);
}
/* Here I need A::calcA(). Instead of duplicating the code,
* I want to call it through X::funcX(). The code compiles,
* but it crashes.
*/
m_w = funcX(0.5, 1.0, \
[this](const double &x, const int &n) \
{ return m_a.calcA(x, n); }, \
m_n);
}
const double getW() const { return m_w; }
};
class Y: public A, public B
{
public:
Y(const int &n, const int &i)
{
// call one of the "virtual public" classes through i
switch (i)
{
case 1: funcA(n); break;
case 2: funcB(n); break;
}
}
void printC() { for (short i=0; i<=m_n; ++i) std::cout << m_c[i] << '\n'; }
void printW() { std::cout << m_w << '\n'; }
void printA(const double &x, const double &n) { std::cout << A::calcA(x, n) << '\n'; }
};
int main(int argc, char *argv[])
{
int N {6};
Y *y;
for (short i=1; i<=2; ++i)
{
y = new Y(N, i);
y->printC();
y->printW();
y->printA(1.2, N);
}
return 0;
}
class X:
X::funcX() is a simple root-finding algorithm which gets called in more than one virtual public classes (A, B, etc). m_c, m_n, m_w are shared variables.
classes A and B:
their main function is funcA() (and funcB(), and so on) and it creates the polynomial (in the body, there's a for loop), based on the calculated order, X::m_n. Evaluating the polynomial is A::calcA(). This needs to be either called by class B, too, or redefined. I'd rather avoid the latter because of the code bloating. It also doesn't look very "professional" for my fairly beginner level...
class Y
This calls any of the virtual public classes based on argument i (the switch/case).
The code compiles, but crashes. It prints the case for. This example points to A::funcA() as the culprit, but in the original program I can see that the coeficients, m_c[i], are not even initialized with dynamic memory, as in trying to print out m_c[0] crashes. I tried moving the new double[] insode the function in A, but that doesn't work.
I don't know how to make it. Does this make sense, is it possible? If yes, how?
Edit: Forgot to add that I can't just move calcA() from A to the top, in X, because each polynomial is evaluated differently, as in there are shortcuts, changes, in every one that makes it possible to have different, optimized evaluations for each polynomial. I could make X::calcA() a universal one, but there will be a performance penalty, which I'd rather not pay.
It seems that your problem is induced by problems with design. When you need to use methods from other class that may mean:
The is a problem with "single responsibility" principle. Class does too much. For example numerical equation solving algorithms are self-sufficient entities and shouldn't be part of polynomial. They can work with any polynomial.
There is a problem with inheritance tree. For example a common ancestor should be created and that common methods should be in it. Note, that if you can't find short and understandable name for that ancestor, then this is not the solution.
Inheritance is not used properly. For example I can't see virtual methods in your code which is strange.
Let's get closer to your example. You are using virtual multiple inheritance which is considered to be very heavy pattern and usually should not be used. Moreover, there are no virtual methods in your code, so you actually do not use inheritance at all. You either must drop inheritance, or think of common methods which make sense for all your classes. For functions this seems to be an ability to calculate function value in specified point. Then move all code, that is not describing polynomials or functions out of the classes. Move out numerical solvers. This will allow to reuse them for all your classes, that support needed interface. Get rid of Y class at all. It seems, that it is needed to emulate virtual methods with switches and enums. You don't need it, rename funcA and funcB just to func if they are semantically the same and do the same thing for different types of polynomials.