Правильно разнести функции по файлам с++ внутри программы

Пишу программу но споткнулся об один момент, как разнести функционал по разным файлам, для удобства чтения..

Файл заголовок win_sockets.h:

int InitializeSockets();

Файл кода win_sockets.cpp:

int InitializeSockets() {
    WSADATA wsaData;
    ADDRINFO hints;
    ADDRINFO* addrResult = NULL;
    SOCKET ConnectSocket = INVALID_SOCKET;
    int result;
    result = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (result != 0) {
        std::cout << "WSA start fail, result = " << result << std::endl;
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;

}

код main.cpp:

 #include "win_sockets.h"
        int main()
        {
            InitializeSockets();
            ...
result = getaddrinfo("127.0.0.1", "22081", &hints, &addrResult);
...

Ошибки VS2019 что:

hints addrResult ConnectSocket

Не определены, как можно это исправить?

Ошибка (активно) E0020 идентификатор "hints" не определен Project5 sender.cpp 17


Ответы (1 шт):

Автор решения: AlexGlebe

I.

Внутри функции объявления переменных

int InitializeSockets() {
  WSADATA wsaData;
  ADDRINFO hints;
  ADDRINFO* addrResult = NULL;
  SOCKET ConnectSocket = INVALID_SOCKET;

работают только при вызове функции, а дальше после окончания работы этих переменных больше не существует. Если вы хотите, чтобы переменные хранились постоянно в единственном экземпляре, то можно их объявить глобальными.

ADDRINFO hints;
ADDRINFO* addrResult = NULL;
SOCKET ConnectSocket = INVALID_SOCKET;

int InitializeSockets() {
  WSADATA wsaData;

А чтобы они были видны при компиляции другого файла, их нужно предварительно объявить в хедере, что они существуют с приставкой extern.

win_sockets.h:

int InitializeSockets();

extern ADDRINFO hints;
extern ADDRINFO* addrResult ;
extern  SOCKET ConnectSocket ;

II.

Если у вас экземпляр сокета не в единичном экземпляре, то желательно создать стуктуру/класс с этими переменными. И передавать указатель/ссылку на данную структуру. Это будет уже не процедурный стиль, а объектный. Тогда можно избавиться от глобальных переменных, и объявить только структуру.

win_sockets.h:

struct stSocket {
  ADDRINFO hints;
  ADDRINFO* addrResult = NULL;
  SOCKET ConnectSocket = INVALID_SOCKET;
};

int InitializeSockets(stSocket * );

win_sockets.cpp:

int InitializeSockets(stSocket * const s) {
  WSADATA wsaData;
  int result;
  result = WSAStartup(MAKEWORD(2, 2), &wsaData);
  if (result != 0) {
    std::cout << "WSA start fail, result = " << result << std::endl;
    return 1;
  }

  ZeroMemory(&s->hints, sizeof(s->hints));
  s->hints.ai_family = AF_INET;
  s->hints.ai_socktype = SOCK_STREAM;
  s->hints.ai_protocol = IPPROTO_TCP;
  return 0 ;
}

main.cpp

#include "win_sockets.h"
int main()
  {
      stSocket s ;
      InitializeSockets( & s );
        ...
    result = getaddrinfo("127.0.0.1", "22081", &s . hints, &s . addrResult);
→ Ссылка