Reputation: 135
Pretty new to C++ programming so be easy on me :)
I am trying to make a program for exercise reasons with C++ and design pattern for it. This are my classes i use right now:
File.cpp-
#include "File.h"
#include <string.h>
File::File() {}
File::~File(void) {}
File.h-
#pragma once
#include <string>
#include <iostream>
using namespace std;
class File
{
public:
//Ctor
File();
//Dtor
~File(void);
//Opens up the file for streaming data I/O
//virtual bool open();
protected:
string _file_name;
};
FileReader.h
#pragma once
#include <fstream>
#include "File.h"
//Handles the input of our file
class FileReader : public File
{
public:
FileReader(string file_name_to_open);
~FileReader(void);
bool isFileOpen();
bool open();
ifstream _in_stream;
};
FileReader.cpp
#include "FileReader.h"
FileReader::FileReader(string file_name_to_open) {
_file_name = file_name_to_open;
open();
}
FileReader::~FileReader(void) { }
bool FileReader::isFileOpen() {
return _in_stream.is_open();
}
bool FileReader::open() {
if(isFileOpen()) {
try{
_in_stream.open(_file_name , ios::in);
} catch(exception exce) {
return false;
}
return true;
} else {
return false;
}
}
Now for some reason once i compile my main that has only
FileReader my_file_reader = FileReader("hello.txt");
i get an error
C2248 - 'std::basic_ofstream<_Elem,_Traits>::basic_ofstream': cannot access private member declared in class 'std::basic_ofstream<_Elem,_Traits>'
Is there a solution for this cuz i tried to so many ways to solve this but didn't found anything good so far.
Thanks
Upvotes: 1
Views: 424
Reputation: 109279
Your FileReader
class contains an ifstream
data member which has a deleted copy constructor. This causes the copy constructor for FileReader
to be implicitly deleted as well, because the compiler generated one would otherwise be ill-formed.
In the statement
FileReader my_file_reader = FileReader("hello.txt");
you use copy-initialization, which requires an accessible copy/move constructor, hence the error. The easiest fix is to use direct-initialization instead:
FileReader my_file_reader("hello.txt");
Now your code will compile. To get the original statement to compile, you'll need to define a move constructor for FileReader
.
FileReader(FileReader&& other)
: _in_stream(std::move(other._in_stream))
{}
And might as well define a move assignment operator too
FileReader& operator=(FileReader&& other)
{
_in_stream = std::move(other._in_stream);
return *this;
}
Note that in case of a C++11 compliant compiler, you don't really need to define a move constructor for your class. To have the compiler implicitly generate one for you, simply get rid of the destructor for FileReader
, which is not doing anything useful anyway. Then your original code will compile without an explicitly defined move constructor. Live demo.
Another option is to explicitly default the move constructor and assignment operators.
FileReader(FileReader&&) = default;
FileReader& operator=(FileReader&&) = default;
which results in the correct behavior too. Unfortunately, neither of these are an option for VS2013. I believe this will be fixed in the next version of VisualStudio.
Upvotes: 1
Reputation: 21003
The problem is that in the line
FileReader my_file_reader = FileReader("hello.txt");
you try to copy FileReader
. And because FileReader
has a member of type ifstream
, this member need to be copied then. But it cannot, because ifstream
s are not copyable. (The error message from the compiler may be misleading - it does not say that you cannot copy, it says that the copy constructor is private).
Please take more care about lifetime and copying of objects in C++. For instance, instead of
FileReader(string file_name_to_open);
you should use
FileReader(const string& file_name_to_open);
Upvotes: 3