2016-06-13 2 views
0

Я вернулся на C++ по прошествии нескольких лет с доказательством концепции. У меня есть файл hpp, который определяет класс, файл cpp с методами класса и main.cpp для тестирования. Я пытаюсь создать tcp-сервер, который работает в своем потоке (только один раз). Я начал со всего кода в том же файле cpp и заставил его работать, но теперь я получаю ошибки компиляции, когда я поместил класс и методы в свои собственные файлы.C++ 11 Как ссылаться на методы класса в других классах или исходных файлах

Я искал, но не нашел ничего, что работает. Я пытался использовать extern, метод «singleton» и т. Д., Которые все приводят к различным сообщениям об ошибках. Я знаю, что я не даю правильной ссылки на методы.

tcpserver.hpp:

#ifndef __TCP_SERVER_HPP_INCLUDED__ 
#define __TCP_SERVER_HPP_INCLUDED__ 

#include <string> 

class Server { 
    public: 

     static void *tcp_server(void * dummy); 
     static void hello(); 
     static int parseCmd(const char *cmd, char *reply); 
     static int copystring(char *reply, const char *msg); 

    private: 

}; 

#endif 

tcpserver.cpp, с методами класса как заглушек:

#include <iostream> 
#include <cstdlib> 
#include <pthread.h> 
#include <unistd.h> 
#include <cstring>  // Needed for memset 
#include <sys/socket.h> // Needed for the socket functions 
#include <netdb.h>  // Needed for the socket functions 
#include <string.h> 

#include "tcpserver.hpp" 

int Server::parseCmd(const char *cmd, char *reply) { 
    //does stuff 
} 


int Server::copystring(char *dst, const char *src) { 
    // does stuff 
    return (int) ((std::string) dst).length(); 
} 


void Server::hello() { 
    std::cout << "Server says 'hello'." << std::endl; 
} 


void *Server::tcp_server(void * dummy) { 
    const char *port = "5555"; 
    // does a lot of stuff 
} 

main.cpp:

#include <iostream> 
#include <pthread.h> 

#include "tcpserver.hpp" 

int main() { 
    Server server; 
    server.hello(); // 'Canary' method FIRST ERROR 

    // Initialize and set thread joinable 
    pthread_attr_t attr; 
    pthread_attr_init(&attr); 
    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); 

    pthread_t serverthread; 
    int rc; 
    // **** tcp_server method must be static **** 
    rc = pthread_create(&serverthread, NULL, server.tcp_server, NULL); 
     if (rc){ 
      std::cout << "Error:unable to create thread," << rc << std::endl; 
      exit(-1); 
     } 
    std::cout << "Main() started thread." << std::endl; 
    pthread_attr_destroy(&attr); 
    void *status; 
     rc = pthread_join(serverthread, &status); 
     if (rc){ 
      std::cout << "Error:unable to join," << rc << std::endl; 
      exit(-1); 
     } 


    return 0 ; 
} 

makefile:

all : main.o tcpserver.o 
    g++ -std=c++11 -o tcpserver main.o tcpserver.o 

tcpserver.o: tcpserver.cpp tcpserver.hpp 
    g++ -std=c++11 tcpserver.hpp 

main.o : main.cpp tcpserver.hpp 
    g++ -std=c++11 main.cpp -lpthread 

clean: 
    rm -f tcpserver.o main.o tcpserver 
+6

Какие сообщения об ошибках вы получаете? Кроме того, '__TCP_SERVER_HPP_INCLUDED__' является зарезервированным именем - не используйте двойные символы подчеркивания. – Barry

+0

Это немного странно (разрешено, но странно), чтобы вызвать статические функции через экземпляр класса. Вы действительно хотите, чтобы эти функции были статичными? – GManNickG

+1

Не связано, но вы можете использовать 'std :: thread' от C++ 11 и далее. 'pthread' теперь просто выглядит yuck! :) – Arunmu

ответ

6

Ваш файл объекта компиляции неверно:

tcpserver.o: tcpserver.cpp tcpserver.hpp 
    g++ -std=c++11 tcpserver.hpp 

main.o : main.cpp tcpserver.hpp 
    g++ -std=c++11 main.cpp -lpthread 

Эти правила не указывают, что вы создаете объектные файлы, они оба говорят, что они независимо друг от друга построения и компоновки приложений. Вот почему вы получаете ошибки компоновщика - вы на самом деле не связываете результат компиляции main.cpp с tcpserver.o.

Необходимо указать -c, чтобы сообщить gcc, что вы не хотите ссылаться, что вы только компиляция. Вам также необходимо предоставить -o, чтобы сообщить, где вывести результаты. И, наконец, вы пытаетесь скомпилировать tcpserver.hpp вместо tcpserver.cpp:

tcpserver.o: tcpserver.cpp tcpserver.hpp 
    g++ -std=c++11 -c tcpserver.cpp -o tcpserver.o 

main.o : main.cpp tcpserver.hpp 
    g++ -std=c++11 -c main.cpp -o main.o 

Или, короче:

%.o : %.cpp tcpserver.hpp 
    g++ -std=c++11 -c $< -o [email protected] 

Кроме того, это правило плохо:

all : main.o tcpserver.o 
    g++ -std=c++11 -o tcpserver main.o tcpserver.o 

Мишень правила all, но на самом деле он делает файл с именем tcpserver. Поэтому, если вы продолжаете переигрывать make, он будет продолжать восстанавливать tcpserver, так как файл all будет продолжать существовать. Измените цель, чтобы она соответствовала фактической цели. И это, где ваши флаги компоновщика идут:

tcpserver : main.o tcpserver.o 
    g++ -std=c++11 -o tcpserver $^ -lpthread 

Кроме того, включают в себя охрану вы используете (__TCP_SERVER_HPP_INCLUDED__) является зарезервированным именем для ++ стандартной библиотеки C. Любое имя, которое содержит двойное подчеркивание или начинается с подчеркивания, за которым следует заглавная буква, не должно использоваться в вашем коде.

+0

Я признаю, что SUPER-rusty с make-файлами (в первую очередь VS-dev в наши дни), но являются файлами .hpp, необходимыми для внесения в make-файл? Я не думал, что они были до тех пор, пока ваши каталоги включений были сделаны правильно и правильно включены в файлы .cpp, и это похоже на то, что в нем находится OP. И может им также понадобиться '-lpthread' или нет? –

+0

@KevinAnderson Они добавляют зависимости для make. Поэтому, если tcpserver.hpp обновлен, main.o нужно будет перестроить. Они необходимы, чтобы убедиться, что вы правильно перестраиваете, хотя вы не хотели бы писать их вручную. – Barry

1

Как указано выше, это проблема с компиляцией, с -lpthread в неправильном месте.

Я Recommand с помощью простого Makefile, пользуясь правил по умолчанию, зависимости и т.д., а также установка всех видов предупреждений

CXXFLAGS = -std=c++11 -Wall -Wextra -pedantic 
LDFLAGS = -lpthread 

tcpserver: main.o tcpserver.o 
    $(LINK.cc) $^ -o [email protected] 

clean: 
    rm -f tcpserver.o main.o tcpserver 

# DO NOT DELETE 

main.o: tcpserver.hpp 
tcpserver.o: tcpserver.hpp 

Примечания: последние 4 строк (начиная с DO NOT DELETE) о зависимости были автоматически добавлены в Makefile командой

makedepend -Y *.cpp 

Эти предупреждения будут полезны для исправления ошибок:

tcpserver.cpp: In static member function ‘static int Server::parseCmd(const char*, char*)’: 
    tcpserver.cpp:14:1: warning: no return statement in function returning non-void [-Wreturn-type] 
} 
^ 
tcpserver.cpp: At global scope: 
tcpserver.cpp:12:34: warning: unused parameter ‘cmd’ [-Wunused-parameter] 
    int Server::parseCmd(const char *cmd, char *reply) { 
            ^
tcpserver.cpp:12:45: warning: unused parameter ‘reply’ [-Wunused-parameter] 
    int Server::parseCmd(const char *cmd, char *reply) { 
              ^
tcpserver.cpp:17:47: warning: unused parameter ‘src’ [-Wunused-parameter] 
    int Server::copystring(char *dst, const char *src) { 
               ^
tcpserver.cpp: In static member function ‘static void* Server::tcp_server(void*)’: 
tcpserver.cpp:29:17: warning: unused variable ‘port’ [-Wunused-variable] 
    const char *port = "5555"; 
        ^
tcpserver.cpp:31:1: warning: no return statement in function returning non-void [-Wreturn-type] 
    } 
    ^
tcpserver.cpp: At global scope: 
tcpserver.cpp:28:33: warning: unused parameter ‘dummy’ [-Wunused-parameter] 
    void *Server::tcp_server(void * dummy) { 
+0

сделать штампы с «отсутствующим разделителем». –

+1

В Makefile были вставлены пробелы, чтобы соответствовать синтаксису Markdown для встроенного кода. Пожалуйста, замените их на таблицы. –

Смежные вопросы