C ++二十一点程序中x86_64架构的未定义符号

时间:2016-09-06 04:48:16

标签: c++

我用C ++编写了一个二十一点游戏,并且多次遇到这个问题,即使我用Google搜索和搜索,他们的解决方案仍然不适合我,所以我想知道哪里出错了。

当我在Clion中编译它时,错误如下:

  

架构x86_64的未定义符号:

     

“Blackjack :: stand()”,引自:

     main.cpp.o中的

_main

     

ld:找不到架构x86_64 clang的符号:错误:链接器命令失败,退出代码为1(使用-v to   见调用)

main.cpp

#include <iostream>

#include "blackjack.h"

using namespace std;

int main() {
    Blackjack bj;
    for (int i = 0; i < 11; ++i) {
        bj.dealerCards.push_back(i);
    }
    for (int i = 0; i < 10; ++i) {
        bj.playerCards.push_back(i);
    }

    bj.stand();
    return 0;
}

blackjack.h

#pragma once

#include <vector>
#include <numeric>

using namespace std;

class Blackjack {

public:
    vector<int> desk; // public only for test, should be protected or private

public: // public only for test, should be protected
    vector<int> dealerCards;
    vector<int> playerCards;

public:
    int hit() {};
    void stand();
};

blackjack_stand.h

#pragma once

#include <iostream>
#include <numeric>

#include "blackjack.h"

void Blackjack::stand() {
    ......
}

2 个答案:

答案 0 :(得分:2)

在源代码文件结构中,虽然blackjack_stand.h包含实现,但它确实根本没有编译,因为编译器通常不直接编译头文件。

您应该将blackjack_stand.h重命名为blackhack_stand.cpp并将该文件与main.cpp一起编译。

答案 1 :(得分:2)

Blackjack::stand的定义不应该在头文件中。头文件用于声明而不是用于定义(请参阅下面的inline例外)。

要理解原因,我们需要学习两个新术语:

  • 声明:通知编译器有关新类,变量或函数的信息。在大多数情况下应该在头文件中。例如,void stand();中的blackjack.h是声明。
  • 定义:此函数\ class函数的实际实现。在大多数情况下应该在.cpp文件中(参见下面的例外情况)。例如,void Blackjack::stand() { ... }是一个定义。

编译代码时,编译器只会读取和编译.cpp文件中的所有常规函数,但它会读取每个.cpp文件中的头文件#include。通过分离定义和声明,我们可以确保我们的代码只存在于我们的程序中一次。

异常 - inline functions:但是,有时候我们会有一点功能,如果它的实现不止一次重复,我们真的不在乎。因此,我们可以在函数定义之前使用内联并将其放在头文件中,我们也可以将它定义为类的一部分:

class B
{
    void foo() { std::cout << "This code will be in every place it called" << std::endl; }
};

inline bar() { std::cout << "This function too!" << std::endl;  }

摘要

为了确保它只编译一次,我们应该始终在.cpp文件中定义我们的函数,并在头文件中声明它们。