I'm running into a situation where I need to use virtual get and set functions to access members of derived classes. However, as pointed out in the answers of this topic (which is quite similar to my problem by the way), this is a bad practice and may mean that my classes need to be redesigned. The thing is... I'm new to C++ and OOP in general, so I'm not sure how exactly I can write my code in a different way.
If you have the patience, I'll explain my situation: I'm working on a code that can solve two different types of problem (say ProblemX and ProblemY). Depending on the user input, you can solve only problemX, only ProblemY, or both at the same time. If you want to solve only ProblemX, you need only a variable named "memberX". If you want to solve only ProblemY, you need only "memberY". If you want to solve both at the same time, you'll need both "memberX" and "memberY", but the problems will depend on each other, so you can't solve each problem individually. In short, the code would be something like this:
#include <vector>
class Problem
{
public:
double memberX;
double memberY;
};
class MainProblem
{
public:
std::vector<Problem*> problems;
};
int main()
{
bool solveProblemX = true; // This variable will depend on user input
bool solveProblemY = true; // This variable will depend on user input
MainProblem * mainProblem = new MainProblem();
for (int i = 0; i < 10000; i++)
{
Problem * problem = new Problem();
mainProblem->problems.push_back(*problem);
}
if (solveProblemX && solveProblemY)
{
// Solve interconnected problem, using "mainProblem->problem[i]->memberX" and "mainProblem->problem[i]->memberY";
}
else if (solveProblemX)
{
// Solve individual problem, using only "mainProblem->problem[i]->memberX";
}
else if (solveProblemY)
{
// Solve individual problem, using only "mainProblem->problem[i]->memberY";
}
else
{
// throw some exception
}
}
So far so good... the real problem is: although I gave only a small sample of the code, my real program is in fact very memory expensive (I actually have a large set of Problem
s, and each contains a large set of members). So, in order to reduce memory usage, I had to make some modifications. For example: If the user chooses to solve only problemX, the variable memberY
will only be a dead weight, since the program won't need it. And vice versa.
Therefore, I thought in making derived classes for ProblemX
and ProblemY
individually, each containing their respectives data member. That way, I can assign to the vector of problems only a minor class containing specifically the data I need. And if I need both, I use another derived class named ProblemXandY
, which containd both memberX
and memberY
. This is the code I thought:
#include <vector>
class Problem
{
public:
virtual double getMemberX(){ // Throw some exception};
virtual double getMemberY(){ // Throw some exception};
};
class ProblemX : public Problem
{
private:
double memberX;
public:
double getMemberX(){ return memberX; };
};
class ProblemY : public Problem
{
private:
double memberY;
public:
double getMemberY(){ return memberY; };
};
class ProblemXandY : public ProblemX, public ProblemY
{};
class MainProblem
{
public:
std::vector<Problem*> problems;
};
int main()
{
bool solveProblemX = true; // This variable will depend on user input
bool solveProblemY = true; // This variable will depend on user input
MainProblem * mainProblem = new MainProblem();
for (int i = 0; i < 10000; i++)
{
Problem * problem;
if (solveProblemX && solveProblemY)
problem = new ProblemXandY();
else if (solveProblemX)
problem = new ProblemX();
else if (solveProblemY)
problem = new ProblemY();
else
// throw some exception
mainProblem->problems.push_back(*problem);
}
if (solveProblemX && solveProblemY)
{
for (int i = 0; i < 10000; i++)
{
double memberX = mainProblem->problems[i]->getMemberX();
double memberY = mainProblem->problems[i]->getMemberY();
// Solve interconnected problem, using "memberX" and "memberY"
}
}
else if (solveProblemX)
{
for (int i = 0; i < 10000; i++)
{
double memberX = mainProblem->problems[i]->getMemberX();
// Solve individual problem, using only "memberX";
}
}
else if (solveProblemY)
{
for (int i = 0; i < 10000; i++)
{
double memberY = mainProblem->problems[i]->getMemberY();
// Solve individual problem, using only "memberY";
}
}
else
{
// throw some exception
}
}
My question is regarding the virtual get functions on the class Problem
. It feels strange, I agree, since the variables memberX
and memberY
don't belong to the class Problem
. However, without it I wouldn't be able to call mainProblem->problems[i]->getMemberX()
, since mainProblem->problems[i]
is an object of the base class Problem
, instead of the derived classes. As I said, my program is memory expensive. That's why I chose to have a single vector of Problem
s in the class MainProblem
, instead of multiple vectors, one for each derived class. Is there something wrong with my structure here? Should I really redesign it? If so, can you think of an alternative?