【问题标题】:C++ extern linkingC++ 外部链接
【发布时间】:2017-10-15 20:38:06
【问题描述】:

我想尝试外部链接和不完整的类型声明并写了这个例子:

来源.cpp:

//Source.cpp
class A {
public: 
   int a=10;
};

A* var1 = new A();

void printA(A* arg)
{
    cout << arg->a << endl;
}

Source1.cpp:

//Source1.cpp
class A
{
public:
    int b = 20;
    int c = 30;
};

A* var2 = new A();

void printB(A* a)
{
    std::cout << a->b;
}

main.cpp:

//main.cpp   
class A;
extern A* var1;
extern A* var2;
int main()
{
    void printA(A*);
    void printB(A*);
    printA(var1); //Prints 10
    printA(var2); //Prints 10
    printB(var2); //Prints 10
    return 0;
}

printA() 的第一次调用之后,正如我所料的那样打印“10”。但是为什么printA()printB()第二次调用后也打印出“10”呢?

【问题讨论】:

    标签: c++ extern incomplete-type


    【解决方案1】:

    欢迎来到违反单一定义规则的精彩世界。您有两个类,都在文件范围内定义,共享一个名称。

    由于默认情况下类具有外部链接,因此您对同一类有两个定义,它们彼此不一致。这会使您的程序格式错误,编译器/链接器可能会抱怨,或者只是继续做一些奇怪的事情。

    另一方面,强制类内部链接的方法是在未命名的命名空间中声明它:

    namespace {
    
        class A {
        public: 
           int a=10;
        };
    
    }
    

    由于未命名的命名空间对于每个翻译单元都是唯一的,因此您实际上将有 两个 单独的类定义。需要注意的是,您不能再从翻译单元外部向它们声明 extern 变量。

    【讨论】:

      【解决方案2】:

      您的程序以不需要诊断的方式违反了单一定义规则,因此格式错误。程序中的两个翻译单元都定义了一个名为A 的类,具有外部链接,但定义不同。允许编译器和链接器假定它们是同一个类。您的程序没有“正确”的输出。

      【讨论】:

      • 所以这是未定义的行为?
      • @Nikita 该标准确实说这是未定义的行为,但我认为他们的意思是说它格式不正确,不需要诊断。如果实际上编译并运行了格式错误的 NDR 程序,则行为未定义。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      • 2019-01-07
      相关资源
      最近更新 更多