Я создаю серверный интерфейс для сетевого программирования, и у меня возникла проблема. Я хочу сделать объект сервера непокрытым, главным образом потому, что на самом деле не имеет смысла это делать и, вероятно, будет создавать проблемы, а также потому, что он использует потоки, которые невозможно скопировать. Однако, когда я делаю оператор-конструктор копирования и оператор присваивания закрытым, я получаю сообщение об ошибке:
Error 2 error C2248: '(namespaces..)::Server::Server' : cannot access private member declared in class '(namespaces..)::Server' (path..)\type_traits 1545 1 Server
Ошибка, кажется, в файле type_traits
? Я не использовал его вообще, хотя возможно, что некоторые из других файлов std
которые я включаю, используют его? Я использую iostream, sstream, string, thread, map
.
Здесь определение класса сервера:
class DLL_PUBLIC Server
{
public:
Server(unsigned int);
~Server();
(...)
private:
class PvtImpl; //Private implementation, so it isn't seen in the header file
PvtImpl *pvtImpl;
Server(const Server &par_other){}
Server& operator=(const Server &par_other){ return *this; }
(...)
};
и частное внедрение:
class Server::PvtImpl
{
public:
bool running;
unsigned int port, backlog, currentlyConnected;
SOCKET listenSocket;
std::thread *acceptConnectionsThread;
std::thread* *receiveDataThreads; //I am using pointers instead of vectors because I want it to be fixed
ClientObj* *clients;
std::map<ClientObj*, unsigned int> clientIndexMap;
};
Поскольку я не знаю, какой код отправлять, потому что я даже не знаю, откуда исходит ошибка, скажите мне, нужна ли вам определенная часть его. Если я прокомментирую конструктор частной копии и оператор присваивания, то он будет работать, но я не хочу, чтобы это было возможно для копирования и, особенно, не с помощью конструктора по умолчанию. Сомневаетесь, но имеет ли это что-то общее с DLL?
В любом случае, это, спасибо за ваше время
Обновить
Поэтому я добавил a = delete
в конструктор, как было предложено, а также сделал его общедоступным:
class DLL_PUBLIC Server
{
public:
Server(unsigned int);
Server(const Server &par_other) = delete;
~Server();
Server& operator=(const Server &par_other) = delete;
(...)
};
Теперь я получаю немного другую ошибку, но также и в файле type_traits:
Error 2 error C2280: '(namespaces..)::Server::Server(const (namespaces..)::Server &)' : attempting to reference a deleted function (path..)\type_traits 1545 1 Server
Немного кода, о котором он жалуется в этом файле:
// TEMPLATE FUNCTION _Decay_copy
template<class _Ty> inline
typename decay<_Ty>::type _Decay_copy(_Ty&& _Arg)
{ // forward _Arg as value of decayed type
return (_STD forward<_Ty>(_Arg));
}
_STD_END
Обновление 2
Итак, это окно вывода из VS по запросу:
1>(path...)\type_traits(1545): error C2280: '(namespaces..)::Server::Server(const (namespaces..)::Server &)' : attempting to reference a deleted function
1> (path..)\Server.h(19) : see declaration of '(namespaces..)::Server::Server'
1> (path..)\thread(47) : see reference to function template instantiation '(namespaces..)::Server std::_Decay_copy<(namespaces..)::Server&>(_Ty)' being compiled
1> with
1> [
1> _Ty=(namespaces..)::Server &
1> ]
1> Server.cpp(94) : see reference to function template instantiation 'std::thread::thread<void(__cdecl &)(const (namespaces..)::Server &),(namespaces..)::Server&>(_Fn,(namespaces..)::Server &)' being compiled
1> with
1> [
1> _Fn=void (__cdecl &)(const (namespaces..)::Server &)
1> ]
Строка 19 в Server.h
которой упоминается, является объявлением конструктора копирования. Строка 94 в Server.cpp
- это создание потоков:
pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, *this);
Функция acceptConnections
берет сервер по постоянной ссылке, поэтому он не должен копировать, вот объявление:
friend void acceptConnections(const Server&);
Ваша проблема наиболее вероятна в конструкторе потоков:
pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, *this);
Попробуйте это вместо этого:
pvtImpl->acceptConnectionsThread = new std::thread(acceptConnections, std::ref(*this));
потому что без оболочки std :: ref() копия экземпляра сервера будет передана в конструктор потока, который, в свою очередь, передаст эту копию по ссылке на ваш метод acceptConnections(). Или, по крайней мере, попытаться, но он так и не дошел, поскольку компилятор не смог выполнить первоначальную копию.