首页 > 解决方案 > c ++模板,两个不同文件中的重复类名,静态初始化

问题描述

我有两个具有相同类名的不同文件(这里:A)。类用于模板特化。专用模板用于静态对象初始化。我希望编译器使用本地类来解决模板,但结果表明它需要两倍的相同专业化。

问题是:如何防止创建这样的代码(可能是一些编译器设置来检测这个),因为它真的很难调试?


------- template.h 

template <typename T>
void Test() {
    T* t = new T();    
    delete t;
}

------- classA1.cpp 

#include <iostream>
#include "template.h"

class A {
 public:
    A() {
        std::cout << "Hello I'm class A(1)" << std::endl;
    }
};

struct Tester1 {
    Tester1() {
        Test<A>();
    }
};

static Tester1 tester1;

------- classA2.cpp 

#include <iostream>
#include "template.h"

class A {
 public:
    A() {
        std::cout << "Hello I'm class A(2)" << std::endl;
    }
};

struct Tester2 {
    Tester2() {
        Test<A>();
    }
};

static Tester2 tester2;

------- main.cpp 

#include <iostream>

int main() {
    std::cout << "Hello from main!" << std::endl;
    return 0;
};

结果:

Hello I'm class A(1)
Hello I'm class A(1)
Hello from main!

标签: c++templates

解决方案


关于一个定义规则

在任何一个翻译单元中只允许对任何变量、函数、类类型、枚举类型或模板进行一个定义(其中一些可能有多个声明,但只允许一个定义)。

一个且只有一个类的定义需要出现在任何翻译单元中,其中该类的使用方式要求它是完整的。

一个程序中可以有多个以下各项的定义:类类型 [...] 只要满足以下所有条件:

[...] - 每个定义都包含相同的标记序列 [...]

你打破了 ODR。对于类类型,如果您破坏 ODR,编译器不会抱怨,但它希望您使用相同的标记序列定义该类。由于编译器期望您的所有同名类定义都是相同的,因此它将只选择其中一个进行链接,然后您将获得您所获得的行为。例如,当您定义两个具有相同名称但定义不同的内联函数时,也会发生同样的情况,只会选择其中一个定义。


推荐阅读