шаблоны c ++, дублированное имя класса в двух разных файлах, статическая инициализация - PullRequest
0 голосов
/ 24 сентября 2019

У меня есть два разных файла с одинаковым именем класса (здесь: 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!

1 Ответ

0 голосов
/ 24 сентября 2019

О Одно правило определения :

В одной единице перевода допускается только одно определение любой переменной, функции, типа класса, типа перечисления или шаблона (некоторые из нихможет иметь несколько объявлений, но допускается только одно определение).

Одно и только одно определение класса требуется для появления в любой единице перевода, где класс используется таким образом, который требует его завершения.

В программе может быть несколько определений каждого из следующих типов: тип класса [...], если выполняется все следующее:

[...]- каждое определение состоит из одинаковой последовательности токенов [...]

Вы нарушаете ODR.Для типа класса компилятор не будет жаловаться, если вы прервете ODR, но ожидает, что вы определили класс с той же последовательностью токенов.Поскольку компилятор ожидает, что все ваши определения классов с одинаковыми именами одинаковы, он выберет только одно из них для связи, и вы получите поведение, которое вы получаете.То же самое происходит, например, когда вы определяете две встроенные функции с одним и тем же именем, но с разными определениями, будет выбрано только одно из определений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...