我正在通过进行小型机器人模拟来学习C ++,而我在类中的静态成员函数遇到了麻烦。
我的环境类定义如下:
class Environment {
private:
int numOfRobots;
int numOfObstacles;
static void display(); // Displays all initialized objects on the screen
public:
Robot *robots;
Obstacle *obstacles;
// constructor
Environment();
static void processKeySpecialUp(int, int, int); // Processes the keyboard events
};
然后在构造函数中我初始化机器人和障碍物,如下所示:
numOfRobots = 1; // How many robots to draw
numOfObstacles = 1;
robots = new Robot[numOfRobots];
obstacles = new Obstacle[numOfObstacles];
以下是使用这些变量的静态函数示例:
void Environment::display(void) {
// Draw all robots
for (int i=0; i<numOfRobots; i++) {
robots[i].draw();
}
}
当我尝试编译时,我收到错误消息,如
error: invalid use of member ‘Environment::robots’ in static member function
我尝试过制作numOfRobots,numOfObstacles,机器人和障碍静态,但后来我遇到了错误
error: undefined reference to 'Environment::numOfRobots'
我非常感谢有人可以解释我做错了什么。 谢谢!
答案 0 :(得分:15)
静态方法不能使用其类中的非静态变量。
这是因为静态方法可以像Environment::display()
一样调用而没有类实例,这使得在其中使用的任何非静态变量都是不规则的,也就是说,它们没有父对象。
您应该考虑为什么要为此目的使用静态成员。基本上,如何使用静态方法的一个例子是:
class Environment
{
private:
static int maxRobots;
public:
static void setMaxRobots(int max)
{
maxRobots = max;
}
void printMaxRobots();
};
void Environment::printMaxRobots()
{
std::cout << maxRobots;
}
您必须在全局范围内初始化变量,例如:
int Environment::maxRobots = 0;
然后,在main
内,您可以使用:
Environment::setMaxRobots(5);
Environment *env = new Environment;
env->printMaxRobots();
delete env;
答案 1 :(得分:3)
这里有两个问题 - 您尝试实现的算法以及无法编译的机制。
为什么不编译。
您正在混合静态和实例变量/方法 - 这很好。但是你不能从静态方法中引用实例变量。这是“无效使用”错误。如果你考虑一下,这是有道理的。只有一个“静态无效显示()”方法。因此,如果它试图引用非静态(实例)变量“机器人”,它指的是哪一个?可能有10个......或者没有。
您尝试实施的逻辑。
看起来你想要一个管理N个机器人的环境类。这是完全合乎逻辑的。一种常见的方法是使Environment成为“单例” - 一个仅允许单个实例的实例变量。然后它可以根据需要分配尽可能多的机器人并自由地引用它们,因为没有静态变量/方法。
另一种方法是继续使整个Environment类静态化。然后保留(静态)机器人列表。但我认为现在大多数人会说选项#1是要走的路。
答案 2 :(得分:2)
static
成员使用它们的成员不需要实例化,因此他们没有this
,因为this
需要实例化:
class foo {
public
void test() {
n = 10; // this is actually this->n = 10
}
static void static_test() {
n = 10; // error, since we don't have a this in static function
}
private:
int n;
};
如您所见,您无法在static
函数内调用实例函数或使用实例成员。因此,如果函数的操作不依赖于实例,并且如果您需要在函数中需要this
的操作,那么函数应该是静态的,您必须考虑为什么我需要调用此函数static
{{1} }}
成员变量是this
,如果它应该在static
的所有实例之间共享,并且它不属于任何特定的class
实例,例如我可能想要一个计数器已创建的班级实例:
class
答案 3 :(得分:2)
第一个错误表示您不能在静态成员函数中使用非静态成员。
第二个说除了声明之外你还需要定义静态成员你必须在类的之外定义静态成员变量 ,在源文件(不在标题中),如下所示:
int Environment::numOfRobots = 0;
您不需要任何静态成员。要拥有绝对正确且可移植的GLUT接口,请使用类型为Environment
的文件级对象和使用C链接声明的文件级(非成员)函数。为方便起见,还有一个名为display
的成员函数。
class Environment
{
public:
void display() { ... }
...
};
static Environment env;
extern "C" void display () { env.display(); }
答案 4 :(得分:1)
静态成员函数是可以在没有该类实际对象的情况下调用的函数。但是,您的函数Environment::display
使用变量numOfRobots
和robots
,它们都存在于Environment
类的特定实例中。要么display
非静态(为什么你想要它是静态的?)或者让机器人成为Environment
的静态成员。
在您的情况下,我认为没有理由提出display
或processKeySpecialUp
static
,因此只需将它们设为正常的成员函数即可。如果您想知道成员函数何时应该是static
,请考虑如果没有创建该类的对象(即没有调用构造函数),该函数是否有意义。如果该函数在此上下文中没有意义,那么它不应该是static
。
答案 5 :(得分:0)
静态方法无法访问实例变量。如果要访问实例变量,请从方法中删除static。如果这些值可以通过所有机器人实例相同,那么将它们设为静态变量,并且该方法可以保持静态。
答案 6 :(得分:0)
如果你想在静态成员函数中访问成员变量只需创建一个成员变量的静态指针并在函数中使用它!!!!!!