1

我无法链接我的程序。所有的类都编译得很好

g++ -c main.cpp
g++ -c Server.cpp
g++ -c Client.cpp

但是当我去链接它们时

g++ main.o Server.o Client.o -o main.out -lsfml-network -lsfml-system

我的客户端和服务器类中的函数得到未定义的引用。

main.cpp:(.text+0x1ba): undefined reference to `(anonymous namespace)::Server::Server()'
main.cpp:(.text+0x1c6): undefined reference to `(anonymous namespace)::Server::getMessage()'
main.cpp:(.text+0x210): undefined reference to `(anonymous namespace)::Server::~Server()'
main.cpp:(.text+0x227): undefined reference to `(anonymous namespace)::Client::Client()'
main.cpp:(.text+0x23d): undefined reference to `(anonymous namespace)::Client::sendMessage(std::string const&)'
main.cpp:(.text+0x287): undefined reference to `(anonymous namespace)::Client::~Client()'
main.cpp:(.text+0x3e9): undefined reference to `(anonymous namespace)::Server::~Server()'
main.cpp:(.text+0x407): undefined reference to `(anonymous namespace)::Client::~Client()'
collect2: error: ld returned 1 exit status

任何帮助深表感谢。


主文件

#include <iostream>
#include <cstdio>
#include <string>
#include "include/Server.hpp"
#include "include/Client.hpp"

void printOptions(std::string const* const, size_t const&);
char const getInput(std::string const* options, size_t const& size);

int main()
{
const std::string YES_NO[] = {
    "Yes",
    "No"
};
const std::string OPTIONS[] = {
    "Server",
    "Client"
};
const std::string CONTINUE = "Continue?\n\n";
const std::string PROMPT = "Run as?\n";
const std::string RECIPEINT = "127.0.0.1";
const size_t SIZE = sizeof(OPTIONS) / sizeof(std::string);

std::cout << PROMPT;
const char INPUT = getInput(OPTIONS, SIZE);

char response;
// Server
if (INPUT == '1')
{
    Server server;
    do
    {
        server.getMessage();
        std::cout << CONTINUE;
        response = getInput(YES_NO, 2);
    } while (response == '1');
}
// Client
else if (INPUT == '2')
{
    Client client;
    do
    {
        client.sendMessage(RECIPEINT);
        std::cout << CONTINUE;
        response = getInput(YES_NO, 2);
    } while (response == '1');
}
// else serious problem
}

/*  Function used to display a list of options to the user.
Each option is displayed on a new line preceeded with
its input number and provided option text.

Ex:
    options[] = {"Option A", "Option B"}
    Will print:
        1) Option A
        2) Option B

@param options
    An array of std::string that will be displayed 
    as the list of options.
@param size
    The number of different options the options array contains.
 */
void printOptions(std::string const* options, size_t const& size)
{
for (size_t i = 0; i < size; i++)
{
    std::cout << i + 1 << ") ";
    std::cout << options[i] << std::endl;
}
}

/*  Used to return a users choice from a list of options.

*WARNING*
    Providing an array with more than 9 options will give
    unexpected return values.

    If it is necesszary to provide a user with mroe than 9 options
    have the 9th option be "More options..." from which you may call
    getInput() again, with additonal options.

@param options
    An array of std::string that will be displayed
    for the users choice.
@param size
    The number of different optins the optinos array contains.

@return const char
    A number from 1 to 9 representing the users choice from 
    the options array.
    1 = array index 0, 9 = array index 8.
 */
const char getInput(std::string const* options, size_t const& size)
{
printOptions(options, size);

char input;
bool needInput = true;
while (needInput)
{
    std::cout << "Enter a number: ";
    std::cin >> input;
    for (size_t i = 0; i < size; i++)
    {
        char optionBuffer[2];
        std::sprintf(optionBuffer, "%zu", i + 1);
        if (input == *optionBuffer)
        {
            needInput = false;
            break;
        }
    }

    if (needInput)
        std::cout << "Option not available." << std::endl;
}

return input;
}

服务器.hpp

#pragma once
#include <SFML/Network.hpp>
#include <iostream>
#include <string>

namespace
{
class Server
{
public:
    Server();
    ~Server();

    static const unsigned short SERVER_PORT = 54000;

    void getMessage();
protected:
private:
    sf::UdpSocket socket;
};
};

服务器.cpp

#include "include/Server.hpp"

//using namespace;

Server::Server()
{
this->socket.bind(SERVER_PORT);
}

Server::~Server() {}

// TODO: Ensure that the socket is bound to a port.
void Server::getMessage()
{
sf::IpAddress   sendersAddress;
unsigned short  sendersPort;
sf::Packet      sendersPacket;

// Failed to recieve packet
if (this->socket.receive(sendersPacket, sendersAddress, sendersPort)
        != sf::Socket::Done
    )
{
    std::cout << "Failed to recieve packet." << std::endl;
}
// Sucessfully recievd packet
else
{   
    std::string message;
    sendersPacket >> message;
    std::cout << "Recieved message:\n\n" << message << std::endl;
}
}

客户端.hpp

#pragma once
#include "Server.hpp"
#include <SFML/Network.hpp>

namespace
{
class Client
{
public:
    Client();
    ~Client();

    void sendMessage(std::string const&);
protected:
private:
    sf::UdpSocket socket;
};
};

客户端.cpp

#include "include/Client.hpp"

//using namespace;

Client::Client()
{
this->socket.bind(sf::Socket::AnyPort);
}

Client::~Client()
{

}

void Client::sendMessage(std::string const& recipient)
{
std::string message;
sf::Packet packet;

std::cout << "Write a message:\n" << std::endl;
do
{
    std::getline(std::cin, message);
} while (!message.size());

socket.send(packet, recipient, Server::SERVER_PORT);
}
4

1 回答 1

3

问题是您ServerClient类声明位于未命名(或匿名)命名空间内。要修复它,只需为您的命名空间命名,例如:

namespace MyNamespace
{
    class Server
    {
        // ...
    };
}

*.cpp文件(包括main.cpp)中,确保您有相应的using指令,例如:

using namespace MyNamespace;

或者,您可以在使用名称时对其进行完全限定,例如,MyNamespace::Server而不是仅Server.

作为旁注,未命名的命名空间实际上是有效的,有时非常有用。当编译器看到一个没有名称的命名空间时,它会为其提供一个唯一的内部名称,并立即在它后面加上一个隐藏using namespace ...指令。这对于您只想在单个*.cpp文件中定义和使用的内容非常有用,因为它可以帮助避免命名冲突。(做类似事情的旧方法涉及static关键字)。

不过,作为一项规则,不要在头文件中使用未命名的命名空间。

于 2013-11-08T00:09:52.460 回答