Ответ 1
Стандартный способ решения этой проблемы - обернуть классы в разные namespaces.
Скажем, у меня есть два разных файла cpp. Оба объявляют классы с одинаковым именем, но, возможно, совершенно другую структуру (или, возможно, одну и ту же структуру, другую реализацию). Классы не отображаются в файлах заголовков. (В качестве примера предположим, что они являются классами Node для разных классов списка.)
Я видел конфликты этих классов. Ожидается ли это по стандарту? Какие решения существуют для этой проблемы?
Стандартный способ решения этой проблемы - обернуть классы в разные namespaces.
Вы можете использовать пространство имен для того, чтобы иметь несколько классов с одинаковым именем, путем подбора их в разных пространствах имен. См.: http://www.cplusplus.com/doc/tutorial/namespaces/
Он нарушает Одно правило определения. Это сложно для компилятора обнаружить ошибку, потому что они находятся в разных единицах компиляции. И даже компоновщик не может обнаружить все ошибки.
См. пример в http://www.cplusplus.com/forum/general/32010/. Мой компилятор и компоновщик (g++ 4.2.1) могут создавать окончательный исполняемый файл без каких-либо ошибок, но вывод неверен.
Если я немного изменил пример, у меня возникла ошибка сегментации.
// main.cpp
#include <iostream>
#include <list>
using namespace std;
struct Handler
{
Handler() : d(10, 1.234) {}
list<double> d;
};
extern void test_func();
int main(void)
{
Handler h;
cout << h.d.back() << endl;
test_func();
return 0;
}
// test.cpp
#include <iostream>
#include <string>
using namespace std;
struct Handler
{
Handler() : d("test Handler") {}
string d;
};
void test_func()
{
Handler h;
cout << h.d << endl;
}
Рекомендуется разграничить класс по пространству имен. Например, Node, вы можете использовать класс nest и определить Node в классе родительского списка. Или вы можете добавить класс в анонимное пространство имен. См. Как тип, который используется только в одном модуле компиляции, нарушает правило одного определения?
Я не уверен, что здесь не хватает некоторых деталей, но вы переносите каждый класс в namespace
.
namespace A {
class Node { };
}
namespace B {
class Node { };
}
Затем вы можете использовать A::Node
или B::Node
.
Я видел конфликты этих классов. Ожидается ли это по стандарту?
В стандарте говорится, что вы не можете этого сделать. Это будет нарушать одно правило определения. (Как исправить это уже было рассмотрено в других ответах)