2012-06-20 121 views
3

我有两个名为file_utils.h和file_utils.cpp的文件,其中包含由不同类使用的一些方法和变量。下面是它的外观的例子:C++ extern关键字和全局变量

file_utils.h:

namespace my_namespace 
{ 
extern Foo* foo; 
extern Bar* bar; 

void my_function(Blah* blah); 
} 

file_utils.cpp

#include "file_utils.h" 

void my_namespace::my_function(Blah* blah) 
{ 
    foo = 0; // undefined reference to my_namespace::foo 
    bar = 0; // undefined reference to my_namespace::bar 
    //... 
} 

some_class.cpp

#include "file_utils.h" 

some_function() 
{ 
    my_namespace::my_function(blah); 
    this->foo = *my_namespace::foo; // will that work ok? 
} 

所以误差在评论。如果我删除了extern关键字,我得到multiple definition of my_namespace::foo错误。问题是什么?从设计角度来看,这甚至是一个好主意,还是应该尝试使用静态成员和方法来代替类?

+5

你必须在**中定义**你的对象。cpp'文件,而'extern'只声明**一个静态链接的对象。 – akappa

回答

7

问题是,你只有宣称为而不是定义为的变量。

您需要提供一个实现文件的定义:

file_utils.cpp

#include "file_utils.h" 

//definition: 
namespace my_namespace 
{ 
    Foo* foo; 
    Bar* bar; 
} 

//alternatively, to keep the same formatting you have 
//Foo* my_namespace::foo; 
//Bar* my_namespace::bar; 

void my_namespace::my_function(Blah* blah) 
{ 
    foo = 0; 
    bar = 0; 
    //... 
} 
+1

我更喜欢你评论过的风格,'Foo * my_namespace :: foo;'。这样,弄错变量名会导致编译错误,而不是默默地声明一个新的变量。 –

+0

@MikeSeymour:尝试编译“namespace ns {} char * ns :: foo;”并看看你得到了什么。 – abarnert

0

首先,我会真的建议你澄清自己两个区别:

  • 声明vs定义
  • 编译器vs链接器

在你的情况你会得到链接错误。未定义的引用意味着,您的代码指向某处,但链接程序无法找出位置。

当您使用在您的代码中找到的某个对象时,extern关键字用于抑制编译器错误。在你的例子中,链接器试图找到你的类的实例,但失败。这是不常用的指针(纠正我,如果我错了)。 因此:

utils.h

namespace mySpace{ 
    extern Foo foo; // notes that foo of type Foo will be used. 

    void myFn(); 
} 

utils.cpp

#include "utils.h" 

void mySpace::myFn(){ 
    foo.bar = 5; // changes a member of foo from globals.cpp 
} 

globals.cpp

Foo mySpace::foo; // this is the actual foo used. 

如果您想要关于some_class.cpp回答的问题,请向社区提供什么是conversions以及您想要实现的内容。

从语义上判断我相信它是对类conversions的成员的引用。

+0

这是一个错字,应该是'my_namespace :: foo'。 – jaho