I'm receiving the message "Use of deleted function" when I combine the use of an ofstream (which I later want to use to record information) and the placement of one class inside another. Here is my minimal example:
#include <iostream>
#include <unistd.h>
#include <fstream>
class Tracker {
private:
std::ofstream tracker_file;
public:
Tracker(const std::string filename) {
tracker_file.open("tracker_file.csv", std::ios_base::app);
}
};
class Penguin {
private:
Tracker p_tracker;
public:
Penguin(
Tracker p_tracker
) : p_tracker(p_tracker) {}
};
int main()
{
Tracker penguin_tracker = Tracker("output");
Penguin gentoo(penguin_tracker);
return 1;
}
I don't understand how these are related, but if I remove the intermediate class then it works, and if I remove the ofstream it works.
CodePudding user response:
In this line in the ctor of Penguin
:
) : p_tracker(p_tracker) {}
You attempt to initalize the Tracker p_tracker
data member.
Since you pass it an existing Tracker
instance, it attempts to use the copy constuctor.
But class Tracker
does not have a copy constructor. This is the "deleted function" mentioned in the error you got.
As @NathanPierson wrote in the comment below, this is because of the deleted copy constructor of the std::ofstream
member variable tracker_file
(and not because of the converting constructor you defined, as I originally wrote).
You could have theoretically solved it by adding a copy ctor to Tracker
, something like:
Tracker(Tracker const & other)
{
// ...
}
However - as mentioned above class Tracker
has a std::ofstream
member which is non copyable.
So the question is what did you mean should happen in this case ?
On a side note: using the same name: p_tracker
for both the class data member and the parameter passed to the constructor is a bit confusing and not recomended.
UPDATE:
To answer the question of the OP in the comment below:
If class Penguin
only needs to keep a refernce to a Tracker
instance, you can do the following (added "m_" prefix to members to diffrentiate them from other variables):
#include <iostream>
#include <fstream>
// No change in Tracker:
class Tracker {
private:
std::ofstream m_tracker_file;
public:
Tracker(const std::string filename) {
m_tracker_file.open("tracker_file.csv", std::ios_base::app);
}
};
// Penguin now holds a reference to Tracker:
class Penguin {
private:
Tracker & m_tracker;
public:
Penguin(
Tracker & tracker
) : m_tracker(tracker) {}
};
int main()
{
Tracker penguin_tracker("output");
Penguin gentoo(penguin_tracker);
return 0;
}
However - this solution requires you to ensure the Tracker penguin_tracker
is alive as long as Tracker penguin_tracker
is alive (otherwise you will have a dangling reference). In your example it is OK, just mentioned in for the general case.
Another side note: main
should return 0 if all went well (not 1). See: What should main() return in C and C ?.