Форум программистов, компьютерный форум CyberForum.ru

Проблема именно с видимостью функций другим файлам - C++

Восстановить пароль Регистрация
 
snyppimylt
 Аватар для snyppimylt
7 / 7 / 1
Регистрация: 18.12.2011
Сообщений: 400
16.02.2014, 23:12     Проблема именно с видимостью функций другим файлам #1
Я создал чисто тестовый пример проекта который создает след. ошибку со строчкой:
strfnc.obj : error LNK2005: "int __cdecl func(int)" (?func@@YAHH@Z) уже определен в testmain.obj
в тест проекте есть 4 файла:

hll.h
100.cpp
strfnc.cpp
testmain.cpp

C++
1
2
3
4
5
6
7
8
// hll.h
#include <windows.h>
#include <iostream>
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* getenv */
#include <conio.h>
#include <string.h>
using namespace std;
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//100.cpp
 
#include "hll.h"
 
class test 
{
 
public:
int a;
 
    void func()
 
    {
        a=1030;
        cout<<a;
return ;
    }
 
};
C++
1
2
3
4
5
6
7
8
9
// strfnc.cpp
 
#include "hll.h"
 
int func(int la)
{
    la=2000;
    return la;
}

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// testmain.cpp
 
#include "hll.h"
#include "100.cpp"
#include "strfnc.cpp"
 
int main()
{
test rt;
rt.func();
 
    cout<<endl<<"100";
int ad =func(1);
    cout<<endl<<ad;
 
getch();
return 0;
}
Подскажите пожалуйста, в чем я не прав? меня интересует проблема именно с видимостью функций другим файлам.

Добавлено через 14 минут
Буду рад помощи
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
16.02.2014, 23:12     Проблема именно с видимостью функций другим файлам
Посмотрите здесь:

Сортировка(именно на С) C++
Какая именно из функций будет вызвана ? C++
Проблема с перегрузками функций C++
C++ Проблема с использованием функций.
C++ Проблема с задачей,а именно с "sqrt"
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
16.02.2014, 23:13     Проблема именно с видимостью функций другим файлам #2
snyppimylt, во всех файлах, кроме того, что с функцией main, напишите в самом верху
C++
1
#pragma once
Tulosba
:)
Эксперт С++
4378 / 3221 / 297
Регистрация: 19.02.2013
Сообщений: 9,044
16.02.2014, 23:25     Проблема именно с видимостью функций другим файлам #3
http://ru.wikipedia.org/wiki/Include_guard
snyppimylt
 Аватар для snyppimylt
7 / 7 / 1
Регистрация: 18.12.2011
Сообщений: 400
18.02.2014, 00:09  [ТС]     Проблема именно с видимостью функций другим файлам #4
Цитата Сообщение от metaluga145 Посмотреть сообщение
snyppimylt, во всех файлах, кроме того, что с функцией main, напишите в самом верху
C++
1
#pragma once
тоже самое.
DrOffset
6461 / 3835 / 886
Регистрация: 30.01.2014
Сообщений: 6,630
18.02.2014, 00:25     Проблема именно с видимостью функций другим файлам #5
Цитата Сообщение от snyppimylt Посмотреть сообщение
тоже самое.
То, что выше посоветовали из другой оперы. Суть в понимании что такое #include и заголовочный файл.
Попробую максимально просто объяснить.
Вот есть у тебя файл А, ты подключаешь туда через include файл B. Это значит, что все содержимое файла B становится частью файла А.
Теперь есть у тебя файл С и ты подключаешь туда опять же файл B. Происходит тоже самое.
Теперь, после этого ты получил два файла, которое абсолютно полностью содержат в себе содержимое файла B (в нашем случае - функцию). т.к. для функций в С++ по умолчанию используется внешнее связывание, то линковщик, видя две одинаковые функции ругается на дубликат.

Побороть это можно по-разному.
Самый нормальный способ - вынести тело функции в отдельный cpp. Тогда повтора тела функции не будет, в заголовочном файле будет только прототип.
Еще можно объявить функцию static - тогда мы запретим внешнее связывание (external linkage) для нее. Это называется внутреннее связывание (internal linkage), когда имя доступно только внутри конкретной единицы трансляции. Функции будет две, по одной в каждой единице трансляции (cpp, модуле), но линкер не будет их друг с другом соотносить, т.к. они во вне не смотрят.
Можно объявить функцию inline - как побочный эффект, inline также устанавливает внутреннее связывание.
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
18.02.2014, 00:37     Проблема именно с видимостью функций другим файлам #6
Цитата Сообщение от DrOffset Посмотреть сообщение
То, что выше посоветовали из другой оперы.
круто объяснили. а теперь читаем про #pragma once; или про include guards, что является тем, что и я написал, только входит в стандарт.
или я чего-то не понимаю?
DrOffset
6461 / 3835 / 886
Регистрация: 30.01.2014
Сообщений: 6,630
18.02.2014, 00:42     Проблема именно с видимостью функций другим файлам #7
Цитата Сообщение от metaluga145 Посмотреть сообщение
или я чего-то не понимаю?
К сожалению.
#pragma once; и include guards защищают только от такого:
C++
1
2
#include <B.h>
#include <B.h>
То есть в перделах одного модуля (не важно сколько вложенностей include'ов было).
Когда в дело вступают разные модули (как у ТС) препроцессор понятия не имеет что где подключалось, поэтому оно не может никак помочь в принципе.
Напомню, что каждый файл в С и С++ транслируется отдельно (отсюда название - единица трансляции).
metaluga145
243 / 244 / 20
Регистрация: 08.04.2013
Сообщений: 927
18.02.2014, 00:55     Проблема именно с видимостью функций другим файлам #8
DrOffset, у него несколько раз подключается файл hll.h, отсюда скорее всего ошибка. как раз от этого и спасают гварды. ему надо просто избежать множественного подключение этого файла.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
18.02.2014, 01:27     Проблема именно с видимостью функций другим файлам
Еще ссылки по теме:

Итерационные циклы,Определение и вызов функций,Использование библиотечных функций stdio.h C++
Функция класса с глобальной видимостью C++
C++ Почему именно C#?

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
DrOffset
6461 / 3835 / 886
Регистрация: 30.01.2014
Сообщений: 6,630
18.02.2014, 01:27     Проблема именно с видимостью функций другим файлам #9
Цитата Сообщение от metaluga145 Посмотреть сообщение
DrOffset, у него несколько раз подключается файл hll.h, отсюда скорее всего ошибка. как раз от этого и спасают гварды. ему надо просто избежать множественного подключение этого файла.
Так. Я просмотрел важный момент, но гварды его все равно не спасут.
В общем проблема не в заголовочном файле, а в том, что он инклудит cpp файлы!
Цитата Сообщение от snyppimylt Посмотреть сообщение
#include "100.cpp"
#include "strfnc.cpp"
Все, что я написал выше, тем не менее, остается правомерным. Только - это не случай ТС.
Спасибо, что вынудил еще раз глянуть на его код

Добавлено через 26 минут
Цитата Сообщение от snyppimylt Посмотреть сообщение
Я создал чисто тестовый пример проекта который создает след. ошибку со строчкой:
strfnc.obj : error LNK2005: "int __cdecl func(int)" (?func@@YAHH@Z) уже определен в testmain.obj
Итак, причина все та же, что описана в моем сообщении про includes (двойное включение содержимого файла подключенного через #include), а так же указанная проблема отсутствия include-guards. То есть проблемы две.

Конкретно к озвученной ошибке привели:
1. Подключение cpp файлов в testmain.cpp. В этом случае они не является единицами трансляции, а просто копируются в testmain.cpp; затем компиляция testmain.cpp, strfnc.cpp и 101.cpp. Получаем три объектных файла с пересекающимся содержимым.

Значит, исправленный код может выглядеть так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// hll.h
#ifndef HLL_H_INCLUDED
#define HLL_H_INCLUDED
//^ include-guards тем не менее следует добавить. Как советовали выше.
 
#include <windows.h>
#include <iostream>
#include <stdio.h>      /* printf */
#include <stdlib.h>     /* getenv */
#include <conio.h>
#include <string.h>
 
class test 
{
public:
    int a;
 
    void func()
    {
        a=1030;
        std::cout<<a;
    }
};
 
int func(int la);
 
#endif
Файл strfnc.cpp
C++
1
2
3
4
5
6
7
#include "hll.h"
 
int func(int la)
{
    la=2000;
    return la;
}
Файл testmain.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// testmain.cpp
 
#include "hll.h"
 
int main()
{
    test rt;
    rt.func();
    cout<<endl<<"100";
    int ad =func(1);
    cout<<endl<<ad;
    getch();
    return 0;
}
Можно для реализации метода класса func тоже добавить cpp файл по аналогии с strfnc.cpp.
Смысл исходного кода оставляю на твоей совести. Только поправил написанное.
Yandex
Объявления
18.02.2014, 01:27     Проблема именно с видимостью функций другим файлам
Ответ Создать тему
Опции темы

Текущее время: 16:49. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru