【问题标题】:Creating separate implementation and header files创建单独的实现和头文件
【发布时间】:2019-01-01 04:17:34
【问题描述】:
//Game Lobby
//Simulates a game lobby where players wait

#include <iostream>
#include <string>

using namespace std;

class Player
{
public:  
    Player(const string& name = "");
    string GetName() const;
    Player* GetNext() const;
    void SetNext(Player* next);

private:
    string m_Name;
    Player* m_pNext;  //Pointer to next player in list
};

Player::Player(const string& name): 
    m_Name(name), 
    m_pNext(0) 
{}

string Player::GetName() const
{
    return m_Name;
}

Player* Player::GetNext() const
{
    return m_pNext;
}

void Player::SetNext(Player* next)
{
    m_pNext = next;
}

class Lobby
{
    friend ostream& operator<<(ostream& os, const Lobby& aLobby);

public:
    Lobby();
    ~Lobby();
    void AddPlayer();
    void RemovePlayer();
    void Clear();

private:
    Player* m_pHead;  
};

Lobby::Lobby():
    m_pHead(0)
{}

Lobby::~Lobby()
{
    Clear();
}

void Lobby::AddPlayer()
{
    //create a new player node
    cout << "Please enter the name of the new player: ";
    string name;
    cin >> name;
    Player* pNewPlayer = new Player(name);

    //if list is empty, make head of list this new player
    if (m_pHead == 0)
    {
        m_pHead = pNewPlayer;
    }
    //otherwise find the end of the list and add the player there
    else
    {
        Player* pIter = m_pHead;
        while (pIter->GetNext() != 0)
        {
            pIter = pIter->GetNext();       
        }
        pIter->SetNext(pNewPlayer);
    }
}

void Lobby::RemovePlayer()
{
    if (m_pHead == 0)
    {
        cout << "The game lobby is empty.  No one to remove!\n";
    }
    else
    {
        Player* pTemp = m_pHead;
        m_pHead = m_pHead->GetNext();
        delete pTemp;
    }
}

void Lobby::Clear()
{
    while (m_pHead != 0)
    {
        RemovePlayer();
    }
}

ostream& operator<<(ostream& os, const Lobby& aLobby)
{
    Player* pIter = aLobby.m_pHead;

    os << "\nHere's who's in the game lobby:\n";
    if (pIter == 0)
    {
        os << "The lobby is empty.\n";
    }
    else
    {
        while (pIter != 0)
        {   
            os << pIter->GetName() << endl;
            pIter = pIter->GetNext();
        }
    }

    return os;
}

int main()
{
    Lobby myLobby;
    int choice;

    do
    {
        cout << myLobby;
        cout << "\nGAME LOBBY\n";
        cout << "0 - Exit the program.\n";
        cout << "1 - Add a player to the lobby.\n";
        cout << "2 - Remove a player from the lobby.\n";
        cout << "3 - Clear the lobby.\n";
        cout << endl << "Enter choice: ";
        cin >> choice;

        switch (choice)
        {
            case 0: cout << "Good-bye.\n"; break;
            case 1: myLobby.AddPlayer(); break;  
            case 2: myLobby.RemovePlayer(); break;
            case 3: myLobby.Clear(); break;
            default: cout << "That was not a valid choice.\n";
        }
    }
    while (choice != 0);

    return 0;
}

大家好!我是 C++ 的初学者,正在做这个问题。该问题提到了以下代码并要求某些解决方案。

问题要求:

  • 测试类 (playerTest.cpp) 的驱动程序文件(主程序)
  • 播放器类头文件和实现文件——单独的接口和实现(player.h & playerImp.cpp)
  • 大厅类头文件和实现文件 -- 单独的接口和实现

由于这是一个实现和标头问题,我尝试研究该主题。我观看了 thenewboston (Bucky)、MissouriSandTCourses、MicrosonicDev 等的 YouTube 视频,但我无法理解任何概念。这本书(Beginning c++ through game programming)在这个话题上根本没有帮助。

我也尝试阅读一些文章,但没有任何帮助。

【问题讨论】:

  • 我不明白你的问题。你能具体说明一下吗?你想达到什么目的?你有什么问题?
  • 相关/欺骗,我认为:stackoverflow.com/questions/9579930/…
  • 问题是要求创建单独的头文件和实现文件: • 测试类的驱动程序文件(主程序)(playerTest.cpp) • 播放器类头文件和实现文件——单独的接口和实现( player.h & playerImp.cpp) • 大厅类头文件和实现文件——单独的接口和实现
  • 你已经把它分开了。现在只需将class 块复制并粘贴到.h 文件中,并将函数实现复制并粘贴到.cpp 文件中。在 .cpp 文件和主文件中包含 .h 文件。就是这样。

标签: c++ class header implementation


【解决方案1】:

以下是您的文件,分为标头和实现。此处遵循声明先于定义的简单原则。包含 #pragma once 的头文件作为包含保护,在任何情况下,这些都包含在源文件中多次。我不建议在头文件中使用using namespace std,尝试将它们移动到源文件并在头文件中使用命名空间限定名称,例如std::string

播放器.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class Player
{
public:  
    Player(const string& name = "");
    string GetName() const;
    Player* GetNext() const;
    void SetNext(Player* next);

private:
    string m_Name;
    Player* m_pNext;  //Pointer to next player in list
};

playerImp.cpp

#include "player.h"

Player::Player(const string& name): 
    m_Name(name), 
    m_pNext(0) 
{}

string Player::GetName() const
{
    return m_Name;
}

Player* Player::GetNext() const
{
    return m_pNext;
}

void Player::SetNext(Player* next)
{
    m_pNext = next;
}

大厅.h

#pragma once

#include <iostream>
#include <string>

using namespace std;

class Player;

class Lobby
{
    friend ostream& operator<<(ostream& os, const Lobby& aLobby);

public:
    Lobby();
    ~Lobby();
    void AddPlayer();
    void RemovePlayer();
    void Clear();

private:
    Player* m_pHead;  
};

lobbyImp.cpp

#include "lobby.h"
#include "player.h"

Lobby::Lobby():
    m_pHead(0)
{}

Lobby::~Lobby()
{
    Clear();
}

void Lobby::AddPlayer()
{
    //create a new player node
    cout << "Please enter the name of the new player: ";
    string name;
    cin >> name;
    Player* pNewPlayer = new Player(name);

    //if list is empty, make head of list this new player
    if (m_pHead == 0)
    {
        m_pHead = pNewPlayer;
    }
    //otherwise find the end of the list and add the player there
    else
    {
        Player* pIter = m_pHead;
        while (pIter->GetNext() != 0)
        {
            pIter = pIter->GetNext();       
        }
        pIter->SetNext(pNewPlayer);
    }
}

void Lobby::RemovePlayer()
{
    if (m_pHead == 0)
    {
        cout << "The game lobby is empty.  No one to remove!\n";
    }
    else
    {
        Player* pTemp = m_pHead;
        m_pHead = m_pHead->GetNext();
        delete pTemp;
    }
}

void Lobby::Clear()
{
    while (m_pHead != 0)
    {
        RemovePlayer();
    }
}

playerTest.cpp

#include "player.h"
#include "lobby.h"

ostream& operator<<(ostream& os, const Lobby& aLobby)
{
    Player* pIter = aLobby.m_pHead;

    os << "\nHere's who's in the game lobby:\n";
    if (pIter == 0)
    {
        os << "The lobby is empty.\n";
    }
    else
    {
        while (pIter != 0)
        {   
            os << pIter->GetName() << endl;
            pIter = pIter->GetNext();
        }
    }

    return os;
}

int main()
{
    Lobby myLobby;
    int choice;

    do
    {
        cout << myLobby;
        cout << "\nGAME LOBBY\n";
        cout << "0 - Exit the program.\n";
        cout << "1 - Add a player to the lobby.\n";
        cout << "2 - Remove a player from the lobby.\n";
        cout << "3 - Clear the lobby.\n";
        cout << endl << "Enter choice: ";
        cin >> choice;

        switch (choice)
        {
            case 0: cout << "Good-bye.\n"; break;
            case 1: myLobby.AddPlayer(); break;  
            case 2: myLobby.RemovePlayer(); break;
            case 3: myLobby.Clear(); break;
            default: cout << "That was not a valid choice.\n";
        }
    }
    while (choice != 0);

    return 0;
}

已编辑

请阅读以下文章以进一步了解 C++ 编译。

https://en.wikipedia.org/wiki/Include_directive

http://faculty.cs.niu.edu/~mcmahon/CS241/Notes/compile.html

https://www.toptal.com/c-plus-plus/c-plus-plus-understanding-compilation

【讨论】:

  • 不要对用户编写的标题使用尖括号。这就是#include "player.h" 的用途。是的,尖括号有效,但它们主要用于编译器提供的头文件。您还应该提到 #pragma once 不是标准 C++。这是一个常见的扩展。
  • 感谢您指出这一点。答案编辑为使用#include "player.h" 格式。
【解决方案2】:

从您当前的源文件开始并进行增量更改。

首先,将class Player的定义移动到名为player.h的文件中;那是一个头文件。然后将Player的成员函数的定义移动到一个名为player.cpp的文件中;这是一个实现文件。

现在您的当前文件将无法编译,因为它不知道class Player。所以添加 `#include "player.h" 到它。

现在对class Lobby 做同样的事情。

现在原始源文件中只剩下int main() 和一些#include 指令。那是你的驱动文件。

【讨论】:

  • 感谢您的回答。移动到单独的文件时,是否必须在每个文件中包含#include &lt;iostream&gt;#include &lt;string&gt;using namespace std;
  • @JamesStewart -- 您需要 #include 您正在编写的文件中需要的任何标题。如果你弄错了,编译器会告诉你。作为一般规则,您不应添加using namespace std;;使用完全限定的名称(例如,std::cout)。
猜你喜欢
  • 2017-12-04
  • 2017-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-14
  • 1970-01-01
  • 2022-01-06
  • 1970-01-01
相关资源
最近更新 更多