【问题标题】:using extern keyword for user defined types in c++在 C++ 中对用户定义的类型使用 extern 关键字
【发布时间】:2015-05-29 16:48:36
【问题描述】:

我想为用户定义的类型使用extern 关键字。这意味着我已经在一个文件中声明了对象并在另一个文件中定义了它。我读过 extern 关键字用于声明变量而不定义它。当程序被拆分成多个源文件并且每个源文件都需要使用全局变量时,extern 关键字很有用。如果我在某处错了,请纠正我。

这是我编写的程序,但不幸的是我做错了什么或遗漏了一些东西,所以我得到了编译器错误。

Prog1.cpp

#include <iostream>
using std::cout;
class test
{
     public:
     void fun();
};
void test::fun()
{
    cout<<"fun() in test\n";
}
test t; 

Prog2.cpp

#include <iostream>
using std::cout;
extern test t;
int main()
{
    t.fun();
}

现在当我编译这两个时使用

g++ -o prog1.cpp prog2.cpp

编译器在 prog2.cpp 中给我以下错误

error: 'test' does not name a type

error:  't' was not declared in this scope

请帮助我知道我在这里做错了什么。

【问题讨论】:

  • extern 告诉编译器 t 的定义在其他地方,但编译器仍然需要 test 的定义,因为您使用 t.fun()编译 Prog2.cpp.
  • 你为什么有使用extern的强烈愿望?
  • @Nawaz:那么这里到底出了什么问题?
  • extern 关键字放在 header 中,而不是 cpp 文件中。 header 的工作是告诉编译器在某处有一个 externally defined 对象。

标签: c++ extern


【解决方案1】:

extern 告诉编译器t 的定义在别处,但编译器仍然需要test 的定义,因为您使用t.fun()编译 @ 987654325@.

所以解决方案是,在定义类的地方写test.h,然后像往常一样在Prog2.cpp 中定义test t。在您的Prog2.cpp 中包含test.h,以便它可以知道test 的定义。然后构建它。

test.h:

#include <iostream>

using std::cout;

class test  //definition of test
{
     public:
     void fun()
     {
        cout<<"fun() in test\n";
     }
};

Prog1.cpp:

#include "test.h"

test t;  //definition of t

Prog2.cpp:

#include <iostream>

#include "test.h"

using std::cout;

extern test t; //the definition of t is somewhere else (in some .o)
               //and the definition of test is in test.h
int main()
{
    t.fun();
}

现在您的代码应该可以编译和链接了。

注意t的定义是链接器在链接时需要的,所以它会在其他.o文件中搜索,但是test的定义是编译器需要的,在compile-时间。

现在应该很明显,您可以将 extern test t; 放在标头本身中,这样您就不必将其写入每个要使用在 Prog1.cpp 文件中定义的对象的 .cpp 文件中(即被编译器变成Prog1.o)。

【讨论】:

  • 为什么要创建头文件?是不是不用头文件就可以了?
  • 这是正确的做法。 Prog2.cpp 需要知道 t 类型为 test 有一个名为 fun 的成员函数。请注意,当编译器将Prog2.cpp 编译为Prog2.o 时,它对其他.cpp 文件一无所知。它是链接从.cpp 文件生成的所有.o 的链接器。
  • @meet:添加了更多细节(最后一行)。
  • 我不知道为什么,但是您给出的解决方案仍然对我不起作用。链接器抱怨并说对 t 错误 id 的未定义引用返回了 1 个退出状态。另一个令人惊讶的是,当我编译它时 prog1.cpp 文件会自动被删除?为什么?我还有什么问题?
  • 谢谢。这是我的错误,我在使用 -o 选项时忘记提及 exe 文件的新名称。我写错了g++ -o Prog1.cpp Prog2.cpp。再次感谢您的宝贵帮助。
【解决方案2】:

extern 关键字放在header 中,而不是cpp 文件中。 header 的工作是告诉编译器某处有一个外部定义的 对象。

例如:

program.h(主要是声明)

struct UserDefinedType
{
    void do_stuff();
};

// declare your global object in the header
// so that the compiler knows its name when
// compiling sources that can not otherwise see
// the object
extern UserDefinedType global_udt;

program.cpp(主要是定义)

#include "program.h"

// define the member functions here
void UserDefinedType::do_stuff()
{
}

// define the global object here
UserDefinedType global_udt;

ma​​in.cpp(使用已在标头中声明定义

#include "program.h" // tells the compiler about global_udt

int main()
{
    // call the global object that is defined
    // in a different source file (program.cpp)
    global_udt.do_stuff();
}

注意:如果我们没有在 header 文件中声明对象 global_udt,那么 ma​​in.cpp 不会知道它的存在,如果我们尝试使用它,编译器会抱怨。

所以 header 只需要 declare 对象而不是 define 它因此需要 extern 关键字.

【讨论】:

    【解决方案3】:

    请注意,在类范围之外声明的变量是具有外部链接的变量(如果没有显式使用 static 关键字)或具有内部链接的变量(如果 static关键字放在变量类型的左边),如果你想在多个文件中使用它,extern是必要的。

    假设这个文件名为 MyVariable.h

    int myNumber = 0; // Initialization of the variable myNumber, external linkage
    static int myStaticNumber; // Initialization of the variable myStaticNumber, internal linkage(only the file in which it's declared)
    

    这个文件是OtherFile.cpp

    extern int myNumber; // Not a initialization because it's already initialized in another file, works fine
    extern int myStaticNumber; // ERROR, this variable has internal linkage!!
    

    您可能想知道为什么 myStaticNumber 被初始化而不是被声明,这是因为 static 变量在默认情况下被初始化为其默认值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-25
      相关资源
      最近更新 更多