質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.36%

ヘッダファイルとセットのcppファイルのコンパイルでリンクエラーが出る。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 318

score 15

Board.hというReversi.hをinclude  したヘッダをBoardTest.cppというファイルにインクルードして、簡易オセロを作りたく、ターミナルで

g++ BoardTest.cpp


と打ち、コンパイルを試みました。すると以下のエラーが出ます。

Undefined symbols for architecture x86_64:
  "Board::move(Point const&)", referenced from:
      _main in BoardTest-07905c.o
  "Board::pass()", referenced from:
      _main in BoardTest-07905c.o
  "Board::undo()", referenced from:
      _main in BoardTest-07905c.o
  "Board::Board()", referenced from:
      ConsoleBoard::ConsoleBoard() in BoardTest-07905c.o
  "Board::isGameOver() const", referenced from:
      _main in BoardTest-07905c.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


リンクでエラーが出ているのはわかるのですが、これは上記のヘッダファイルとcppがリンクされていないということでしょうか?
また、なぜそうなっているのでしょうか?

それぞれのコードは以下です。

Board.h
#ifndef REVERSI_H_INCLUDED
#define REVERSI_H_INCLUDED

#include <string>
#include <sstream>
#include <stdexcept>

const int BOARD_SIZE =  8;
const int MAX_TURNS  = 60;


typedef int Color;

const Color EMPTY = 0;
const Color WHITE = -1;
const Color BLACK = 1;
const Color WALL  = 2;



struct Point
{

    int x;
    int y;

    Point()
    {
        Point(0, 0);
    }

    Point(int x, int y)
    {
        this->x = x;
        this->y = y;
    }

    Point(std::string coordstr) noexcept(false)
    {
        if(coordstr.length() < 2)
            throw "The argument must be Reversi style coordinates!";

        x = coordstr[0] - 'a'+1;
        y = coordstr[1] - '1'+1;
    }

    operator std::string() const
    {
        std::ostringstream oss;
        oss << static_cast<char>('a'+x-1) << static_cast<char>('1'+y-1);

        return oss.str();
    }

    bool operator==(const Point& p) const
    {
        if(x != p.x) return false;
        if(y != p.y) return false;

        return true;
    }
};
/*
bool operator==(const Point& lhs, const Point& rhs)
{
    if(lhs.x != rhs.x) return false;
    if(lhs.y != rhs.y) return false;

    return true;
}*/

struct Disc : public Point
{
    Color color;

    Disc() : Point(0, 0)
    {
        color = EMPTY;
    }

    Disc(int x, int y, Color color) : Point(x, y)
    {
        this->color = color;
    }
};

template<typename T> class ColorStorage
{
    T data[3];
public:
    T& operator[](int color)
    {
        return data[color+1];
    }

    const T& operator[](int color) const
    {
        return data[color+1];
    }

    ColorStorage<T>& operator +=(const ColorStorage<T> &src)
    {
        data[0] += src.data[0];
        data[1] += src.data[1];
        data[2] += src.data[2];

        return *this;
    }

};

#endif

BoardTest.cpp

#include <iostream>
#include "Board.h"

using namespace std;


class ConsoleBoard : public Board
{
public:
    void print()
    {
        cout << "  a b c d e f g h " << endl;
        for(int y=1; y<=8; y++)
        {
            cout << " " << y;
            for(int x=1; x<=8; x++)
            {
                switch(getColor(Point(x, y)))
                {
                case BLACK:
                    cout << "●";
                    break;
                case WHITE:
                    cout << "◯";
                    break;
                default:
                    cout << " ";
                    break;
                }
            }
            cout << endl;
        }
    }
};

ostream& operator<<(ostream& os, const Point& p)
{
    string s = p;
    os << s;
    return os;
}

int main()
{
    ConsoleBoard board;

    while(true)
    {
        board.print();
        cout << "黒石" << board.countDisc(BLACK) << " ";
        cout << "白石" << board.countDisc(WHITE) << " ";
        cout << "空きマス" << board.countDisc(EMPTY) << endl;


        vector<Point> movables = board.getMovablePos();
        for(unsigned i=0; i<movables.size(); i++)
        {
            cout << movables[i] << " ";
        }
        cout << endl << endl;

        cout << "手を入力してください";
        Point p;

        string in;
        cin >> in;

        if(in == "p")
        {

            if(!board.pass())
                cerr << "パスできません" << endl;

            continue;
        }

        if(in == "u")
        {
            // undo
            board.undo();
            continue;
        }

        try
        {

            Point parse(in);
            p = parse;
        }
        catch(const char* e)
        {
            cerr << "リバーシ形式の手を入力してください!" << endl;
            continue;
        }

        if(board.move(p) == false)
        {
            cerr << "そこには置けません" << endl;
            continue;
        }

        if(board.isGameOver())
        {
            cout << "----------------ゲーム終了----------------" << endl;
            return 0;
        }
    }

    return 0;

}

Board.h

#ifndef BOARD_H_INCLUDED
#define BOARD_H_INCLUDED

#include "Reversi.h"
#include <vector>

class Board
{
public:
    Board();

    void init();
    bool move(const Point& point);
    bool pass();
    bool undo();
    bool isGameOver() const;

    unsigned countDisc(Color color) const
    {
        return Discs[color];
    }

    Color getColor(const Point& p) const
    {
        return RawBoard[p.x][p.y];
    }

    const std::vector<Point>& getMovablePos() const
    {
        return MovablePos[Turns];
    }

    std::vector<Disc> getUpdate() const
    {
        if(UpdateLog.empty()) return std::vector<Disc>();
        else return UpdateLog.back();
    }

    Color getCurrentColor() const
    {
        return CurrentColor;
    }

    unsigned getTurns() const
    {
        return Turns;
    }

    std::vector<Point> getHistory() const
    {
        std::vector<Point> history;

        for(unsigned i=0; i<UpdateLog.size(); i++)
        {
            std::vector<Disc> update = UpdateLog[i];
            if(update.empty()) continue; 
            history.push_back(update[0]);
        }

        return history;
    }

    unsigned getLiberty(const Point& p) const
    {
        return Liberty[p.x][p.y];
    }


private:


    static const unsigned NONE        =   0;
    static const unsigned UPPER       =   1;
    static const unsigned UPPER_LEFT  =   2;
    static const unsigned LEFT        =   4;
    static const unsigned LOWER_LEFT  =   8;
    static const unsigned LOWER       =  16;
    static const unsigned LOWER_RIGHT =  32;
    static const unsigned RIGHT       =  64;
    static const unsigned UPPER_RIGHT = 128;


    Color RawBoard[BOARD_SIZE+2][BOARD_SIZE+2];
    unsigned Turns;
    Color CurrentColor;

    std::vector<std::vector<Disc> > UpdateLog;

    std::vector<Point> MovablePos[MAX_TURNS+1];
    unsigned MovableDir[MAX_TURNS+1][BOARD_SIZE+2][BOARD_SIZE+2];
    unsigned Liberty[BOARD_SIZE+2][BOARD_SIZE+2];

    ColorStorage<unsigned> Discs;

    void flipDiscs(const Point& point);
    unsigned checkMobility(const Disc& disc) const;
    void initMovable();

};

#endif
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • int32_t

    2021/02/22 15:07

    提示されているコード、BoardTest.cpp の部分の中身が Reversi.h では?

    キャンセル

  • NASIJIRU

    2021/02/22 15:14

    仰るとおりでした。
    失礼しました。
    訂正します。

    キャンセル

回答 2

checkベストアンサー

0

g++ BoardTest.cpp Board.cpp

コンパイラは、Board.h で宣言された関数の実装がどこにあるのかは知りません。ですので、コマンドラインで実装が入っているファイルも指定する必要があります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/02/22 15:11

    表記していただいたコマンドで出来ました。ありがとうございます。
    ベストアンサーにさせていただきます。

    キャンセル

0

mainが見当たらんのですが。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2021/02/22 15:09

    main関数はBardTest.cppに入っているので動くのかなとおもってコンパイルしてました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.36%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る