Тема: Простір імен в header файлі, багаторазове підключення

Мені потрібно оголосити простір імен в header файлі

namespace MyNamespace 
{
    class A;
}

але до сього файлу підключені два source файла і за того я отримую помилку LNK1169
Error    LNK1169 one or more multiply defined symbols found

extern тут не допоможе бо це клас а не об'єкт

Як уникнути цієї помилки ?

2

Re: Простір імен в header файлі, багаторазове підключення

Будь ласка, наводьте повністю мінімальний код, що демонструє вашу проблему. Ви що, в .h файлі #include "...cpp" пишете, чи що? Без цього якось не виходить відтворити.

Подякували: Arete, leofun012

3 Востаннє редагувалося Betterthanyou (21.05.2016 00:45:49)

Re: Простір імен в header файлі, багаторазове підключення

A.h

#pragma once
#include <stdio.h>
#include <conio.h>
#include <typeinfo>

namespace MyNamespace 
{
    class A;
}

template <class t>
class A
{
public:
    A();
};

template <class t> A<t>::A()
{
    printf("Print A\n");
    printf("type = %s\n", typeid(t).name());
}

A.cpp

#include "A.h"
#include "B.h"


int main()
{
    B b;

    A<B> a;

    getch();
    return 0;
}

B.h

#pragma once
#include "A.h"

class B : public A<int>
{
public:
    B();
};

B.cpp

#include "B.h"

B::B()
{
    printf("Print B\n");
}

До помилки LNK1169, можна ще додати помилку з шаблонами LNK2019   
LNK2019    unresolved external symbol "public: __thiscall A<int>::A<int>(void)" (??0?$A@H@@QAE@XZ) referenced in function "public: __thiscall B::B(void)" (??0B@@QAE@XZ)
Вона виникає коли я намагаюся реалізацію перенести в A.cpp файл, а якщо оставити реалізацію конструктора в A.h тоді залишається лише помилка
LNK1169 one or more multiply defined symbols found

Коли я забрав A.h то код успішно компілюється

//#include "A.h"
#include "B.h"

int main()
{
    B b;

    //A<B> a;

    getch();
    return 0;
}
Подякували: leofun011

4

Re: Простір імен в header файлі, багаторазове підключення

На VS2010 компілюється нормально.
Виводить:

Print A
type = int
Print B
Print A
type = class B
Post's attachments

TestTemplate2.zip 3.7 kb, 135 downloads since 2016-05-21 

Подякували: koala, Betterthanyou2

5

Re: Простір імен в header файлі, багаторазове підключення

Не бачу тут проблем. MyNamespace::A і ::A<...> - різні типи, і ніяк не перетинаються.
Ще LNK1169 можна отримати, якщо проголошувати не-inline і не-template в хедері та якщо лишати зайві копії файлів хедерів. Або ви десь використовували using і не навели в прикладі.
Зрештою, можете додавати і #pragma once, і include guards - перше для швидкості, друге для стандартів.

Так, а ще:
- в C++ рекомендовано використовувати засоби з iostream замість cstdio;
- вже бозна скільки ця бібліотека в C++ зветься cstdio, а не stdio.h;
- conio.h - це бібліотека для роботи з функціями операційної системи MS DOS, померлої 20 років тому; навіть її клони вже використовують інші засоби;
- ви використовуєте функцію з conio.h в main, а включаєте її в A.h - це спеціально, щоб додати роботи компілятору і, у випадку помилки, собі?

Подякували: Betterthanyou, leofun012

6 Востаннє редагувалося Betterthanyou (21.05.2016 15:31:03)

Re: Простір імен в header файлі, багаторазове підключення

Дивно, але коли я створив новий проект цей код в мене таж запрацював, а на старому помилка.
Можливо я щось в налаштуваннях "накрутив" і вже забув (в мене microsoft visual studio 2015)

Вибачаюсь.


А які бібліотеки використовувати для роботи з консоллю ?
Я знаю що можна передавати консольні команди за допомогою функції system("") (вона має бутив #include <stdlib.h>) ну і conio яка справді не працює, наприклад clrscr вже немає (або називається інакше)
Windows API Consoles  - це хороший варіант ? Чи є щось краще ?

7

Re: Простір імен в header файлі, багаторазове підключення

system("cls"); - тільки для Windows подібних систем.
http://www.cplusplus.com/forum/articles/10515/#msg49080