我用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() {
......
}
答案 0 :(得分:2)
在源代码文件结构中,虽然blackjack_stand.h
包含实现,但它确实根本没有编译,因为编译器通常不直接编译头文件。
您应该将blackjack_stand.h
重命名为blackhack_stand.cpp
并将该文件与main.cpp
一起编译。
答案 1 :(得分:2)
Blackjack::stand
的定义不应该在头文件中。头文件用于声明而不是用于定义(请参阅下面的inline
例外)。
要理解原因,我们需要学习两个新术语:
void stand();
中的blackjack.h
是声明。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文件中定义我们的函数,并在头文件中声明它们。