骰子游戏c++错误未声明的标识符/代码审查
Dice Game c++ error undeclared identifier/code review
我正在做大家最喜欢的c++入门项目。骰子游戏。我真的很难理解c++是如何来回发送信息的,以及如何在单独的文件中使用函数和类。我最大的问题是为什么我在每个变量上得到未声明的标识符?…
histogram.h
#pragma once
#include "stdafx.h"
#include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
typedef unsigned int uint;
uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };
class Dice
{
public:
void inline rollDie(uint rolls)
{
for (i = 1; i <= rolls; i++) {
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
++frequency[die1 + die2];
}
}
};
histogram.cpp
#include "stdafx.h"
#include "histogram.h"
using namespace std;
class theHisto
{
public:
void printHisto()
{
for (int i = 1; i < 12; i++)
{
//Output some asterisks for the histogram
for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
cout << "*";
cout << endl;
}
}
};
main.cpp
#include "stdafx.h"
#include "histogram.h"
#include "histogram.cpp"
using namespace std;
uint main()
{
cout << "How many times would you like to roll the dice?";
cin >> rolls;
Dice myDice;
myDice.rollDie(rolls);
theHisto mytheHisto;
mytheHisto.printHisto();
}
对不起,如果这是混乱的,但当我复制代码到"输入代码在这里"框,它只是显示为常规文本,所以我不得不缩进每一行4个空格,所以格式可能有点off....
首先,不要#include "histogram.cpp"
,这是所有问题的根源。具体来说:
- 编译器将从
main.cpp
或histogram.cpp
开始,最有可能是main.cpp
。然后,它将继续从每个.cpp
文件创建一个单一的翻译单元,通过预处理它并包括#include
指令指定的每个文件。 - 预处理
main.cpp
时,会遇到#include "histogram.h"
。这告诉预处理器将文件histogram.h
粘贴到main.cpp
的顶部,也就是它遇到这一行的地方。然后,它将继续对histogram.h
的内容进行预处理,直到到达从文件粘贴的代码的末尾,并移动到main.cpp
中的下一行。 - 在预处理从
histogram.h
粘贴进来的代码时,会遇到#include "histogram.cpp"
。这告诉预处理器将文件histogram.cpp
粘贴到那里,就像它对histogram.h
所做的那样。然后,它将继续对histogram.cpp
的内容进行预处理,直到它到达从文件粘贴的代码的末尾,并继续移动到从histogram.h
粘贴的下一行。 -
#pragma once
将阻止stdafx.h
、histogram.h
和histogram.cpp
被多次复制粘贴,预处理将正常完成。[注意,#pragma once
可能会也可能不会防止main.cpp
中的#include "histogram.cpp"
,因为它在histogram.h
中而不是main.cpp
中。]同样,如果stdafx.h
包含任何内容,它可能会遇到同样的问题;我假设它是空的,并且是由您的IDE自动插入的,因此只会在翻译单元的顶部提到它一次。编译现在将开始,使用以下文件:// Contents of "stdafx.h" here. using namespace std; class theHisto { public: void printHisto() { for (int i = 1; i < 12; i++) { //Output some asterisks for the histogram for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--) cout << "*"; cout << endl; } } }; // Contents of <cstdlib> here. // Contents of <stdio.h> here. // Contents of <iostream> here. typedef unsigned int uint; uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0; uint frequency[12] = { 0 }; class Dice { public: void inline rollDie(uint rolls) { for (i = 1; i <= rolls; i++) { die1 = 1 + rand() % 6; die2 = 1 + rand() % 6; ++frequency[die1 + die2]; } } }; // Contents of "histogram.cpp" may also be here. using namespace std; uint main() { cout << "How many times would you like to roll the dice?"; cin >> rolls; Dice myDice; myDice.rollDie(rolls); theHisto mytheHisto; mytheHisto.printHisto(); }
请注意,histogram.cpp
的主体现在被放在histogram.h
的主体之前,意思是:
-
frequency
在声明前使用。 -
rolls
在声明之前使用。 -
std::cout
在遇到#include <iostream>
之前使用。 -
std::endl
在#include <iostream>
之前使用。 - 如果编译器不尊重
#pragma once
,类theHisto
将被重新定义。
因此,您会得到"undefined variable used"错误。
相反,您希望编译器同时编译histogram.cpp
和main.cpp
,并在链接阶段将它们组合起来。既然我们已经在每个.cpp
文件的开头添加了#include "stdafx.h"
,那么就不需要在histogram.h
中做同样的事情了。
接下来,theHisto
应该在histogram.h
中定义,而不是histogram.cpp
。
// histogram.h
#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
typedef unsigned int uint;
uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };
class Dice
{
public:
void inline rollDie(uint rolls)
{
for (i = 1; i <= rolls; i++) {
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
++frequency[die1 + die2];
}
}
};
class theHisto
{
public:
void printHisto();
};
和
// histogram.cpp
#include "stdafx.h"
#include "histogram.h"
using namespace std;
void theHisto::printHisto()
{
for (int i = 1; i < 12; i++)
{
//Output some asterisks for the histogram
for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
cout << "*";
cout << endl;
}
}
这将解决错误,但会导致链接错误,因为您的全局变量是在多个编译单元中定义的。为了解决这个问题,您可以在histogram.h
中将它们声明为extern
,并在.cpp
文件之一中定义它们。
// histogram.h
#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
typedef unsigned int uint;
extern uint rolls, i, die1, die2, output, show;
extern uint frequency[12];
class Dice
{
public:
void inline rollDie(uint rolls)
{
for (i = 1; i <= rolls; i++) {
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
++frequency[die1 + die2];
}
}
};
class theHisto
{
public:
void printHisto();
};
和
// histogram.cpp
#include "stdafx.h"
#include "histogram.h"
using namespace std;
uint rolls = 0, i = 0, die1 = 0, die2 = 0, output = 0, show = 0;
uint frequency[12] = { 0 };
void theHisto::printHisto()
{
for (int i = 1; i < 12; i++)
{
//Output some asterisks for the histogram
for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
cout << "*";
cout << endl;
}
}
和
// main.cpp
#include "stdafx.h"
#include "histogram.h"
// #include "histogram.cpp"
using namespace std;
// You could define your variables here, instead of in "histogram.cpp", if you wanted.
uint main()
{
cout << "How many times would you like to roll the dice?";
cin >> rolls;
Dice myDice;
myDice.rollDie(rolls);
theHisto mytheHisto;
mytheHisto.printHisto();
}
这将解决链接错误,并允许您的代码编译。注意,编译器的命令行应该同时指定main.cpp
和histogram.cpp
,并且可能看起来像这样(假设是Visual Studio,因为stdafx.h
)。
cl /EHsc main.cpp histogram.cpp
或者,您可以通过将theHisto::printHisto()
定义为内联来完全消除histogram.cpp
。
// histogram.h
#pragma once
// #include "stdafx.h"
// #include "histogram.cpp"
#include <cstdlib>
#include <stdio.h>
#include <iostream>
typedef unsigned int uint;
extern uint rolls, i, die1, die2, output, show;
extern uint frequency[12];
class Dice
{
public:
void inline rollDie(uint rolls)
{
for (i = 1; i <= rolls; i++) {
die1 = 1 + rand() % 6;
die2 = 1 + rand() % 6;
++frequency[die1 + die2];
}
}
};
using namespace std;
class theHisto
{
public:
void printHisto()
{
for (int i = 1; i < 12; i++)
{
//Output some asterisks for the histogram
for (int freq = (frequency[i] * 100 / rolls); freq > 0; freq--)
cout << "*";
cout << endl;
}
}
};
和
// main.cpp
#include "stdafx.h"
#include "histogram.h"
// #include "histogram.cpp"
using namespace std;
uint main()
{
cout << "How many times would you like to roll the dice?";
cin >> rolls;
Dice myDice;
myDice.rollDie(rolls);
theHisto mytheHisto;
mytheHisto.printHisto();
}
这个将用下面的代码编译,再次假设Visual Studio:
cl /EHsc main.cpp
前面两个中的任何一个都应该解决您的问题。我建议使用前者,因此您也可以将Dice::rollDie()
移动到histogram.cpp
,就像我对theHisto::printHisto()
所做的那样。只要记住不要#include
任何.cpp
文件,除非1)它们包含在任何它们所依赖的代码之后的,以及2)您只在单个文件中#include
它们,该文件应该有一个头保护。请注意,如果你知道你在做什么,以及如何安全地打破第二条规则,你可以完成很多疯狂的把戏。一般来说,最好告诉编译器将每个.cpp
文件作为一个单独的翻译单元来处理,而不是将它们组合成一个单独的、大量的blob。
[参见对这个答案的第一条评论,其中包含进一步的建议;它们不应该是让你的代码工作所必需的,但是会很有用。如果有的话,最有可能打破的是main()
的返回类型;虽然unsigned int
可以隐式地转换为int
,但并不是每个编译器都同意main()
返回unsigned int
而不是int
。
我看到你的代码有一些问题。我不知道这是否解决了你的问题,因为你没有发布错误信息。
- 方法
main()
应该返回int
。 -
frequency
数组太小。或者die1
和die2
的值太大。这要看你怎么看了 - 你正在混合c++和C头文件。包含
cstdio
而不是stdio.h
。最好不要使用cstdio
和cstdlib
。你不需要他们。 - 使用
unsigned
作为数据类型,而不是你自己定义的uint
。 - 你没有初始化你的随机数生成器
- 我的代码中有错误,未声明的标识符
- 提供对不同类型的数据(建议、代码审查)的线程安全访问的类
- 代码审查:常量字符 * 修改
- Stroustrup的代码审查-编程原理-Ch-4-问题:3-错误:矢量下标超出范围
- 代码的错误答案是在Java Camel案件和C 下划线标识符之间转换的错误答案
- 如何在性能和VMS上对C++进行代码审查/调试/编码/测试/版本控制
- 在给定的代码中获取错误(标识符未定义)
- 简单代码问题-未定义标识符
- C++错误代码 C2065:"<类名>"未声明的标识符,即使它应该在另一个 .h 文件中声明
- 代码审查,C++,字谜方法
- 我是否可以在不使用资源的情况下为Win32控件分配标识符代码
- 视觉 这个C++代码有什么问题?(未声明的标识符)
- 在代码C2065 VS2010 C++的同一部分中声明和未声明的标识符
- 为什么我的简单 c++ 代码无法编译?我收到未声明的标识符?
- vc++ 2010 -未声明的标识符在DLL中的尝试,少量代码
- 在从书中复制的代码中获取未声明的标识符
- 骰子游戏c++错误未声明的标识符/代码审查
- 简单的c++计算器代码审查
- 未定义行为:代码审查的检查表
- C ++链表不释放内存 - 寻找快速代码审查