patterncppMinor
Is usage of friend class appropriate in this case?
Viewed 0 times
thiscaseappropriateusagefriendclass
Problem
I want to have a class that stores data from an input file, for use in a simulation program. It is like a struct but may require some small functions for accessors.
A seperate class reads all the data from a text input file. I want to store most of this data in the above mentioned object. Therefore this class needs to be able to set the data variables.
My current approach is to give the loader class friend access, so that these variables can be set. No other classes should be able to set the data, therefore I am not using setters.
Is this appropriate friend class usage?
I have included a demonstration example of the situation, as simple as possible:
In reality the data holder I have called "Pod" here, holds 10 to 20 different strongly related variables.
A seperate class reads all the data from a text input file. I want to store most of this data in the above mentioned object. Therefore this class needs to be able to set the data variables.
My current approach is to give the loader class friend access, so that these variables can be set. No other classes should be able to set the data, therefore I am not using setters.
Is this appropriate friend class usage?
I have included a demonstration example of the situation, as simple as possible:
In reality the data holder I have called "Pod" here, holds 10 to 20 different strongly related variables.
#include
class Pod {
// holds the data that will be used later in simulation
friend class Loader;
public:
double get_angle() {return angle_ * 3 / 180;};
protected:
double angle_;
};
class Loader {
// loads data from text file.
public:
bool CheckFile() {
// checks file:
return true;
}
Pod ReadData() {
double a = 90; // this line simulates reading from file.
Pod pod;
pod.angle_ = a;
return pod;
}
};
void DoesThingsWithData(Pod data) {
std::cout << data.get_angle() << std::endl;
}
int main() {
Pod my_data;
{
Loader loader;
if (loader.CheckFile()) {
my_data = loader.ReadData();
}
}
// do things with data
DoesThingsWithData(my_data);
return 0;
}Solution
Personally, I don't have major objections with that design. It gets the job done in a fairly straightforward way. But it does creates coupling, which might become a nuisance to you as the project grows. So another option with less coupling, as mentioned in comments, would be defining a default parameterized constructor:
In C++11, you also don't have to worry about unnecessary copies of complex objects such as a
class Object {
public:
Object();
private:
};
class Loader {
public:
Object LoadObject()
{
// many fields of data...
int a = ...
double b = ...
std::vector c = ...
return Object(a, b, std::move(c), ...);
}
};In C++11, you also don't have to worry about unnecessary copies of complex objects such as a
std::vector. You can make the constructor take a move ref, e.g.: std::vector && vec and apply std::move in the call site.Code Snippets
class Object {
public:
Object(<several params>);
private:
<the data>
};
class Loader {
public:
Object LoadObject()
{
// many fields of data...
int a = ...
double b = ...
std::vector<int> c = ...
return Object(a, b, std::move(c), ...);
}
};Context
StackExchange Code Review Q#68485, answer score: 4
Revisions (0)
No revisions yet.