提问人:mjsyts 提问时间:9/22/2022 最后编辑:mjsyts 更新时间:9/22/2022 访问量:152
C++ 主要语法错误?(12 个重复的符号用于建筑x86_64)[复制]
C++ Major syntax error? (12 Duplicate Symbols for architecture x86_64) [duplicate]
问:
为我的无知道歉。我对另一种语言的 C++ 比较陌生。我正在制作一个程序来对扑克牌进行排名,但我遇到了一个我不明白的错误,但我假设这是一个主要的语法错误。请友善,我正在努力学习。这不会在 Xcode 中构建。当我尝试时,我收到以下错误消息:
12 建筑x86_64的重复符号
我真的对这个错误感到困惑。这是我的代码:
扑克.hpp
#ifndef poker_hpp
#define poker_hpp
#include <stdio.h>
#include <iostream>
#include <array>
#include <string>
#include <algorithm>
#include <vector>
using namespace std;
const size_t HAND_ARRAY_SIZE = 5;
const size_t CARD_ARRAY_SIZE = 2; //just in case, might not use it
typedef array<string, HAND_ARRAY_SIZE> hand_t; //typedef for poker hands
typedef array<string, CARD_ARRAY_SIZE> card_t; //just in case, might not use it
const size_t SUIT_ARRAY_SIZE = 4;
static array<string, SUIT_ARRAY_SIZE> suits =
{"C", "D", "H", "S"};
const size_t VALUE_ARRAY_SIZE = 13;
static array<string, VALUE_ARRAY_SIZE> ranks_ace_high =
{"2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K", "A"};
static array<string, VALUE_ARRAY_SIZE> ranks_ace_low =
{"A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K"};
const size_t HAND_RANK_ARRAY_SIZE = 10;
//EDIT: added static
static array<string, HAND_RANK_ARRAY_SIZE> handRanks =
{
"high card",
"pair",
"two pair",
"three of a kind",
"straight"
"flush",
"full house",
"four of a kind",
"straight flush",
"royal flush"
};
class Hand {
private:
hand_t cards;
string type();
float value();
bool acesLow();
public:
Hand(hand_t cards);
};
#endif /* poker_hpp */
test_hands.cpp
#include "poker.hpp"
hand_t test0 {"TC", "9C", "8C", "7C", "6C"};
hand_t test1 {"8H", "7H", "6H", "5H", "4H"};
hand_t test2 {"8H", "7H", "6H", "5H", "4H"};
hand_t test3 {"6S", "5S", "4S", "3S", "2S"};
hand_t test4 {"7D", "6D", "5D", "4D", "3D"};
hand_t test5 {"7S", "6S", "5S", "4S", "3S"};
hand_t test6 {"KS", "KH", "KC", "KD", "3H"};
hand_t test7 {"7H", "7D", "7S", "7C", "QH"};
hand_t test8 {"7H", "7D", "7S", "7C", "QH"};
手.cpp
#include "poker.hpp"
Hand::Hand(hand_t cards){
this->cards = cards;
}
main.cpp
#include "poker.hpp"
#include "test_hands.cpp"
int main() {
Hand hand(test0);
};
答:
有两个问题。在包含文件时,include 指令将在预处理阶段有效地替换为命名文件的内容。这将生成一个大文件,其中包含源文件的内容以及所有包含的标头以及编译的其他标头包含的所有标头。
这意味着在头文件中定义某些内容时必须小心:包括头文件在内的每个人都将拥有自己的定义副本,这将违反一个定义规则,除非您采取额外步骤将定义锁定在正在编译的翻译单元中(链接或匿名命名空间)或告诉编译器所有副本都是相同的(函数)。static
inline
在 poker.hpp 中,
array<string, HAND_RANK_ARRAY_SIZE> handRanks = { ... };
没有或绑定在匿名命名空间中,因此每个包含的源文件都定义了一个对象,当链接器将所有内容放在一起时,它找到了所有对象并拒绝继续。static
handRanks
handRanks
第二个问题是主要的.cpp包括test_hands.cpp。这复制了 test_hands.cpp 中的所有内容.cpp。IDE 将 test_hands.cpp 和 main.cpp发送到编译器,每个源代码的输出都包含在 test_hands.cpp 中定义的所有内容,从而导致更多多个定义。不要包含 cpp 文件。而是编译和链接它们。
test_hands.cpp中需要向其他文件公开或由其他文件共享的任何内容都应在其他源文件包含的标头中声明。Extern
将在这里提供帮助。也就是说,在本例中,只需将测试数据构建到 main.cpp 中即可。没有充分的理由将测试数据与测试驱动程序分开,除非它很大或很复杂,并且你希望尽可能少地编译它。
战术说明:
在进入构造函数的主体之前,所有类成员和基类都已完全初始化。这意味着在
Hand::Hand(hand_t cards){
this->cards = cards;
}
member 默认初始化(这反过来又默认初始化 s),然后成员被参数覆盖,使初始化浪费了精力。一个好的优化编译器可能会发现这种浪费并消除它,但相反,你可以利用成员初始值设定项列表,通过准确说明你想要的行为,使编译器的工作更轻松。cards
HAND_ARRAY_SIZE
string
cards
cards
Hand::Hand(hand_t cards): cards(cards){
}
成员现在使用参数 进行复制初始化。请注意,我们还可以毫不含糊地重复使用该名称。cards
cards
cards
当您的数据结构具有编译器无法轻易消除的昂贵默认初始化时,这一点非常重要,而当基类或成员变量无法默认初始化时,这一点至关重要。
评论
static
handRanks