|
|
|
Правила раздела Visual C++ / MFC / WTL (далее Раздела)
error LNK2005, исправление.
, Якобы уже определен класс
- Подписаться на тему
- Сообщить другу
- Скачать/распечатать тему
|
|
В Visual C++ 6 необходимо разбить программу на ООП на файлы, так, чтобы один файл (*.h) содержал сам класс, аналогичный *.cpp файл содержал функции этого класса. Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(char *,char *,char *)» (??0Chelovek@@QAE@PAD00@Z) already defined in Chelovek.obj Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(char *)» (??0Chelovek@@QAE@PAD@Z) already defined in Chelovek.obj Kursach.obj : error LNK2005: «public: __thiscall Chelovek::Chelovek(void)» (??0Chelovek@@QAE@XZ) already defined in Chelovek.obj При это, есть файл Chelovek.h с таким содержанием: #ifndef CHELOVEK_H #define CHELOVEK_H #include <fstream.h> class Chelovek { protected: char Name[15]; char Family[15]; char Otchestvo[15]; public: int ID; Chelovek(char *Nm,char *Fm,char *Ot); Chelovek(char *Fm); Chelovek(); ~Chelovek(){}; virtual void print()= 0;// Чистая виртуальная функция virtual int fwrite()= 0; virtual int Fwrite(fstream f)= 0;// Чистая виртуальная функция virtual int fread()=0;// Чистая виртуальная функция virtual int Fread(ifstream f)= 0; }; #endif А файл Chelovek.cpp имеет такое содержание: #include «Chelovek.h» #include <string.h> Chelovek::Chelovek(char *Nm,char *Fm,char *Ot) { ID=0; strcpy(Name,Nm); strcpy(Family,Fm); strcpy(Otchestvo,Ot); } Chelovek::Chelovek(char *Fm) { ID=0; strcpy(Family,Fm); } Chelovek::Chelovek() { char *y; y=»»; ID=0; strcpy(Name,y); strcpy(Family,y); strcpy(Otchestvo,y); }
А в основном файле просто инклудится Chelovek.cpp. Заранее всем спасибо. Сообщение отредактировано: антиКИЛЛЕР — 21.06.08, 13:39 |
Juni |
|
// h class Chelovek //cpp Chelovek::Chelovek(char *Fm) Chelovek::Chelovek() попробуй Сообщение отредактировано: Juni — 21.06.08, 13:54 |
антиКИЛЛЕР |
|
Juni, f:институткурсовая тех прогkursachchelovek.h(17) : error C2653: ‘std’ : is not a class or namespace name f:институткурсовая тех прогkursachchelovek.h(19) : error C2653: ‘std’ : is not a class or namespace name F:ИНСТИТУТКурсовая Тех прогKursachKursach.cpp(173) : error C2248: ‘Name’ : cannot access private member declared in class ‘Chelovek’ f:институткурсовая тех прогkursachchelovek.h(6) : see declaration of ‘Name’ Далее список ошибок приводить не буду, т.к. они относятся к тому, что программа не может получить доступ к данным private. В случае, если просто убрать такие строки: #ifndef CHELOVEK_H #define CHELOVEK_H … #endif то возникает ошибка открытия файла Chelovek.obj: LINK : fatal error LNK1104: cannot open file «.DebugChelovek.obj» Error executing link.exe. |
антиКИЛЛЕР |
|
По ходу компилятор переглючил. Сейчас запустил и теперь уже находится Chelovek.obj и возникают те же самые ошибки error LNK2005. |
Hryak |
|
Цитата антиКИЛЛЕР @ 21.06.08, 13:38 А в основном файле просто инклудится Chelovek.cpp.
Проблема в том, что ты инклудишь .cpp-файл. Так не делается. |
антиКИЛЛЕР |
|
Hryak, |
0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
0 пользователей:
- Предыдущая тема
- Visual C++ / MFC / WTL
- Следующая тема
[ Script execution time: 0,0300 ] [ 16 queries used ] [ Generated: 9.02.23, 21:07 GMT ]
у меня есть 3 cpp-файла, которые выглядят так
#include "Variables.h"
void AppMain() {
//Stuff...
}
все они используют одни и те же переменные внутри них, поэтому у них одинаковые заголовки, но я получаю такие вещи
1>OnTimer.obj : error LNK2005: "int slider" (?slider@@3HA) already defined in AppMain.obj
почему это?
7 ответов
имейте в виду, что #include примерно так же, как вырезание и вставка включенного файла внутри исходного файла, который включает его (это грубая аналогия, но вы понимаете суть). Это означает, если у вас есть:
int x; // or "slider" or whatever vars are conflicting
в файле заголовка, и этот файл заголовка включен тремя исходными файлами в программу, тогда все они будут иметь глобальное имя x, определенное, которое будет конфликтовать.
что вы хотите сделать, это определить переменную как extern, так что .cpp файлы будут заявление, а потом в одном из ваших .cpp файлы дают фактическое определение.
в переменные.h:
extern int x;
В SomeSourceFile.cpp
int x;
конечно, я бы рекомендовал против глобалов, но если вы должны использовать их, это удержит их от конфликта.
16
автор: James Michael Hare
это потому, что компилятор компилирует каждый .cpp
файл отдельно, создавая .obj
файл для каждого из них. Ваш заголовок, похоже, имеет что-то вроде:
int slider;
когда это включено в каждый из ваших трех вы получаете три копии int slider
переменная, как если бы вы объявили ее в каждом . Компоновщик жалуется на это, потому что у вас нет трех разных вещей с одним и тем же именем.
что вы, вероятно, хотите сделать, это изменить файл заголовка, чтобы прочитать:
extern int slider;
это говорит компилятору, что есть slider
переменная где-то, но, возможно, не здесь, и позволяет компоновщику понять это. Затем в один :
int slider;
дает компоновщику одну фактическую переменную для связи.
потому что «int slider» уже определен в другом файле? Проверьте, что у вас есть защита заголовка…
#ifndef _VARIABLES_H_
#define _VARIABLES_H_
int slider;
#endif
если он находится в нескольких единицах перевода, и вы хотите, чтобы переменные были разными (т. е. не глобальными), то, возможно, объявите их в анонимном пространстве имен:
namespace {
int slider;
}
Если вы хотите, чтобы они были глобальными, посмотрите на решение Джеймса.
что происходит, так это то, что каждая из переменных из переменных.h дается глобальная область для каждого из отдельных файлов C. Когда компоновщик собирает все файлы C, он видит несколько переменных с одинаковым именем.
Если вы хотите использовать переменные из файла заголовка в качестве глобальных переменных, вам придется использовать ключевое слово «extern» перед всеми из них, а в главном файле не используйте ключевое слово extern.
главная c:
int n_MyVar;
другие файлы:
extern int n_MyVar;
Вы можете создать две переменные файлов.h И EVariables.h, или просто объявите переменные в main.файл cpp.
гораздо лучший способ сделать это-создать класс переменных и передать ссылку на класс.
Я знаю, что это старый поток, но я наткнулся на это как один из первых результатов поиска от Google. Я решил проблему, поместив переменную static.
namespace Vert
{
static int i;
}
я попробовал extern и в моей ситуации, которая, похоже, не решила проблему.
этой ошибки связывания также можно избежать, если переменные включены несколько раз через «переменные».h » объявляются как const.
у меня тоже была эта ошибка, хотя я работаю с определениями extern. Проблема заключалась в инициализации переменных в определениях extern:
ID3D11VertexShader* g_pVertexShader = nullptr;
...
extern ID3D11VertexShader* g_pVertexShader = nullptr; // here's the problem
=> ошибка
ID3D11VertexShader* g_pVertexShader = nullptr;
...
extern ID3D11VertexShader* g_pVertexShader; // without initializing
=> нет ошибок, проблема решена
Я пытался решить проблему, связанную с модулями компиляции.
Я получаю ошибку
1>frtinvxml.obj : error LNK2005: "struct repFieldInfo det_rep_info" (?det_rep_info@@3UrepFieldInfo@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct repFieldInfo frt_rep_info" (?frt_rep_info@@3UrepFieldInfo@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct FormToolbar * tb" (?tb@@3PAUFormToolbar@@A) already defined in Frtinv.obj
1>frtinvxml.obj : error LNK2005: "struct tagDATE_STRUCT dateFrom" (?dateFrom@@3UtagDATE_STRUCT@@A) already defined in Frtinv.obj
... (It goes on for every variable and method in the header...)
Это единственная ошибка, которую я получаю. Вот включения для каждого соответствующего класса, участвующего в порядке от самого высокого на дереве до самого низкого …
***Frtinv.hxx***
#pragma once
#include <voyage.ddh>
#include <vsched.ddh>
# ...
struct frtinvType : public frtinv_type
{
int fixCarSeq;
...
…
***frtinv.cxx***
//#define _IN_MAIN_
#include <decisionTable.h>
...
#define RINDEX 2
#define LINDEX 2
#define PINDEX 0
BOOL s_fNeedSaveAfterDelete = FALSE;
static int rateCnt = RINDEX, lumpCnt = LINDEX, pcntCnt = PINDEX;//------------------------------------------------------------------------
int getPortcar(char *vslCode, int voyNo, int portCallSeq, int berthSeq, int seq, portcar_type *pret)
...
…
***frtinvxml.h***
#define _IN_MAIN_
#include <iostream>
#include <sstream>
#include <stdio.h>
#include <zdb.hxx>
#include <opr32.h>
#include <voyage.ddh>
#include <frtinv.ddh> <------ Tried to add these two to the solution, that failed.
#include <frtinv.hxx> <------
void exitGracefully();
std::list<voyage_type> getVoyages();
…
***frtinvxml.cpp***
#include "frtinvxml.h" <------ taking everything from frtinvxml.h
void main(int argc, char *argv[]) {
InitWinLib (10, 8);
...
Моя проблема связана с тем, что даже если я помещаю файлы в одну папку / решение, я не могу заставить их не определять себя дважды. Даже при использовании ключевого слова Pragma Once. Я также попытался использовать старую школу #define, не включайте, если она уже существует … это тоже не сработало.
Есть ли у вас какие-либо решения или рекомендации?
-1
Решение
#pragma once
предотвращает многократное включение заголовка в одну единицу компиляции — в данном случае файл .obj — и ошибка прямо заявляет, что frtinvxml.obj определяет то, что уже было определено в Frtinv.obj. Два отдельных объекта. Два отдельных сборника.
once
отлично работал в случае Frtinv.obj и снова в случае frtinvxml.obj. Оба имеют одно и то же определение, иначе источники не были бы скомпилированы. К сожалению, компоновщик пытается поместить оба объекта в один и тот же вывод.
Два решения для этого, в зависимости от того, как переменная будет использоваться, но для обоих не делать объявления в заголовках. Это почти всегда плохо кончается.
Определение:
extern struct repFieldInfo det_rep_info;
в соответствующем заголовке. extern
говорит компилятору это где-то det_rep_info
будет объявлено, и компиляция должна продолжать использовать этот внешний det_rep_info
,
В файле cpp, frtinvxml.cpp, Frtinv.cpp или в каком-то третьем cpp, который содержит общие данные, объявите
struct repFieldInfo det_rep_info;
Затем сделайте то же самое с остальными тремя дублирующимися переменными.
Точно, где поместить эти переменные, зависит от личного вкуса, выбора и стандарта кодирования. Скомпилируйте этот файл и свяжите его с другими файлами .obj, чтобы каждый мог получить доступ к переменной.
Объявляет:
static struct repFieldInfo det_rep_info;
в каждом файле cpp, который требует этого. Повторите для всех необходимых переменных. static
гарантирует, что каждый det_rep_info
виден только в определенной области. В этом случае один блок компиляции. Там на самом деле немного тонкости, так что читать документацию Чтобы убедиться static
подходит для вас.
Вы можете поместить объявление в заголовок, и каждый включающий заголовок получит свою собственную копию, но важно отметить, что каждый включающий заголовок получит копию, хотят они этого или нет. Не принимайте это решение за других людей. Объявите переменную в нужных файлах cpp. Компилятор поймает его, если вы пропустите один.
4
Другие решения
Других решений пока нет …
15 ответов
Если вы внимательно прочитали ошибку компоновщика и примените некоторые знания, вы можете попасть туда сами:
Компонент связывает несколько скомпилированных объектов и библиотек вместе, чтобы получить двоичный файл.
Каждый объект/библиотека описывает
- какие символы он ожидает присутствовать в других объектах
- какие символы он определяет
Если два объекта определяют один и тот же символ, вы получаете именно эту ошибку компоновщика. В вашем случае как mfcs80.lib, так и MSVCRT.lib определяют символ _DllMain @12.
Как избавиться от ошибки:
- узнать, какая из двух библиотек вам действительно нужна
- узнайте, как рассказать компоновщику не использовать другой (используя, к примеру, отзыв от Джеймса Хопкина).
xtofl
05 дек. 2008, в 11:19
Поделиться
У меня было такое же сообщение об ошибке, но ни один из ответов здесь не разрешил для меня.
Поэтому, если вы столкнулись с этой проблемой при создании DLL-проекта, который использует MFC, его можно решить, введя следующую строку:
extern "C" { int _afxForceUSRDLL; }
в файл cpp, где DllMain
определен. Затем используется ваша собственная реализация DllMain
, а не одна из dllmain.obj.
Когда мы пытаемся использовать библиотеку MFC, мы обязательно включим afx.h напрямую или косвенно, то MFC (afx.h) сообщает компоновщику, чтобы найти символ __afxForceUSRDLL и поместите этот объект, который содержит __afxForceUSRDLL в программу, поэтому линкер выполняет поиск и помещает dllmodule.obj в наш потому что __afxForceUSRDLL определяется в dllmodule.cpp.
Это общий сценарий. Когда мы хотим использовать наш собственный DllMain в mfc dll project, компоновщик жалуется, что есть два DllMain, один в наш код, один в Dllmodule.obj.
Итак, нам нужно сказать компоновщику, чтобы добавить наш dllmain.obj для __afxForceUSRDLL. Поэтому нам нужно определить __afxForceUSRDLL в нашем собственном файле cpp, где определен наш собственный DllMain, тогда компоновщик будет игнорировать mfcs dllmodule.obj и видеть только один DllMain и никогда не жалуется.
Источник: http://social.msdn.microsoft.com/Forums/en-US/0d78aa6b-1e87-4c01-a4a7-691335b7351a/how-to-build-mfc-application-dll-in-visual-c-2010
Constantin
12 нояб. 2013, в 14:33
Поделиться
Если вы определяете свой собственный DllMain, в настройках вашего проекта вам нужно установить «Использовать MFC» в «Свойства конфигурации/Общие» для «Использовать стандартные библиотеки Windows».
Вы должны сделать чистую перестройку после ее изменения.
James Hopkin
05 дек. 2008, в 10:40
Поделиться
Для меня прямая причина была действительно отсутствующей ссылкой на символ _afxForceUSRDLL, но косвенной причиной было отсутствие определения макроса _USRDLL. Он определяется по умолчанию мастером VC, но иногда разработчики стирают его ошибочно.
Вот несколько слов.
Ofek Shilon
06 май 2015, в 05:49
Поделиться
В моем проекте я смог решить эту проблему, добавив mfcs80.lib и msvcrt.lib в качестве дополнительных зависимостей в настройках проекта. «Дополнительные зависимости» можно найти в Linker → Input.
В конфигурации отладки, которая должна быть mfcs80d.lib и msvcrtd.lib соответственно.
Кстати, я работаю с Visual Studio 2010, поэтому в моем случае MFC lib называется mfc100.lib.
Я не уверен, почему это сработало. Нет необходимости добавлять эти файлы lib в качестве дополнительных зависимостей, потому что я уже установил «Использование MFC» в «Использовать MFC в общей DLL». Я предполагаю, что, указав эти библиотеки в качестве дополнительных зависимостей, они связаны в другом порядке.
Это решение более или менее совпадает с тем, которое предлагается на сайте Microsoft: http://support.microsoft.com/kb/148652, за исключением того, что мне не нужно вводить все в поле «Игнорировать конкретные библиотеки по умолчанию».
vmb100
05 июль 2012, в 13:59
Поделиться
Для всех тех, кто испытывает эту ошибку в проектах ATL (в основном при попытке добавить поддержку MFC), вот решение, которое я нашел после нескольких дней разочарования!
Прежде всего, эта ссылка была для меня более полезной, чем все остальные. Он указал мне в правильном направлении. Проблема возникает, если по какой-то причине «сгенерированные файлы» (содержащие прокси-сервер и код-заглушки, так же как и типы) были удалены и прочитаны в проекте. Это заставляет Visual Studio добавлять их в неправильном порядке!
Обычно вы сначала сталкиваетесь с ошибкой «ATL требует компиляции С++», но вы можете исправить это, отключив параметр Yc/Yu
(предварительно скомпилированные заголовки) для этого файла.
Что вы должны сделать дальше, это разгрузить проект и отредактировать его. Найдите группы товаров, которые определяют порядок сборки и включают порядок (ClCompile
и ClInclude
). Проверьте их порядок и настройки.
Компиляторы должны отображаться в следующем порядке:
-
dllmain.cpp
(сCompileAsManaged
установлено значениеfalse
иPrecompiledHeader
осталось пустым). - Источник библиотеки (
MyLib.cpp
, содержащийDllCanUnloadNow
и т.д.) - Код прокси-сервера (
MyLib_i.c
; с теми же настройками, что иdllmain.cpp
) -
stdafx.cpp
(сPrecompiledHeader
установлено значениеCreate
) - Все остальные исходные файлы библиотеки (фактическое содержимое библиотек)
-
xdlldata.c
(с теми же настройками, что иdllmain.cpp
)
Затем заказы должны быть упорядочены следующим образом:
-
dllmain.h
-
MyLib_i.h
-
Resource.h
-
stdafx.h
-
targetver.h
- … (фактические заголовки библиотек)
-
xdlldata.h
Фиксирование порядка сборки зафиксировал мой проект, и я смог создать новую чистую сборку.
Carsten
13 янв. 2015, в 10:19
Поделиться
Идентификатор базы знаний MSDN Q148652.
http://support.microsoft.com/kb/148652
Причина:
Visual С++ компилирует исходные файлы в алфавитном порядке и передает скомпилированные объектные файлы в компоновщик в алфавитном порядке.
Если компоновщик сначала обрабатывает DLLDATAX.OBJ, исходный код ссылается на DllMain, который компоновщик загружает из MSVCRTD.LIB(dllmain.obj).
Затем компоновщик обрабатывает объектный файл, скомпилированный из файла С++, который содержит #include «stdafx.h», который ссылается на символ
__afxForceUSRDLL, который компоновщик загружает из MFC42D.LIB(dllmodul.obj). Этот объектный модуль также содержит реализацию для DllMain,
вызывая конфликт.
Bill
06 сен. 2013, в 07:38
Поделиться
В моем случае у меня была проблема с директивами препроцессора.
По какой-то причине _USRDLL
был определен, когда он не должен был быть.
Чтобы проверить это, перейдите в меню Project , выберите Project Properties , затем выберите фрагмент Configuration Properties → Preprocessor .
Здесь будут найдены директивы препроцессора.
joan
19 авг. 2014, в 19:31
Поделиться
Просто #undef
_USRDLL
перед включением afx.h
или даже лучше отредактируйте конфигурацию проекта и удалите макрос.
Это обычная конфигурация для DLL расширения MFC: Настройки сборки для MFC DLL
mgruber4
02 дек. 2015, в 23:37
Поделиться
У меня очень похожая проблема. [mfcs110d.lib(dllmodul.obj): ошибка LNK2005: _DllMain @12 уже определена в MSVCRTD.lib(dllmain.obj)], и решение было добавить mfcs110d.lib в дополнительные зависимости
joseAndresGomezTovar
24 апр. 2014, в 08:32
Поделиться
Я лично избавился от этой ошибки следующим образом: проект с правой кнопкой мыши в Solution Explorer
, выбранном Properties
из всплывающего меню, нажал вкладку Linker
и добавил mfcs71ud.lib
в Additional Dependencies
. Если вы используете Visual Studio 2005, это должно быть «80» вместо «71» и т.д.
izogfif
20 апр. 2013, в 21:34
Поделиться
Убедитесь, что вы включили «Stdafx.h» в начало каждого файла .cpp. Я получал ту же ошибку и имел единственный .cpp файл, который вообще не включал этот заголовок. Добавление #include решило проблему.
Matt Davis
10 июнь 2016, в 04:03
Поделиться
Объявите mfc80ud.lib
и mfcs80ud.lib
в поле Additional Dependancies
в Project Properties -> Linker Tab -> Input of Visual Studio
, чтобы устранить проблему.
Avishek Bose
09 окт. 2015, в 04:22
Поделиться
Я нашел это, что помогло мне:
http://support.microsoft.com/kb/148652
В основном порядок компоновщика был неправильным. CRT libs связывались перед библиотекой MFC. Оказывается, библиотеки MFC должны были быть связаны FIRST, а затем библиотеки CRT могли быть связаны.
Yucko Microsoft!!
C Johnson
22 окт. 2014, в 17:06
Поделиться
Я нашел решение здесь
Порядок компоновки библиотек Visual Studio 2010
это:/FORCE: MULTIPLE
в вариантах компоновщика
Мне пришлось смешивать ATL и MFC вместе, чтобы использовать
[module (name = «mymodule» )]; в приложении MFC вместе с ключевым словом «__hook»
Serov Danil
23 май 2014, в 15:33
Поделиться
Ещё вопросы
- 0Как стилизовать кнопку Тип ввода в HTML
- 0Невозможно очистить данные, когда нет результата, используя внешнюю фильтрацию в UI.Grid (Angular)
- 1Исключение среды выполнения развертывания Azure
- 1Снимок экрана синхронно
- 1Как сделать так, чтобы оси занимали несколько вспомогательных участков при использовании графика даты и времени панд?
- 0Ionic App вылетает при потере фокуса [дубликата]
- 0mysql.exe выходной файл CSV в Windows
- 1Есть ли способ изменить атрибуты узла карты сайта во время выполнения?
- 1Python Datareader не может извлечь данные о запасах из Morningstar
- 0Как сделать отступ в элементе
- 0Подтвержденная форма JQuery не отправляется
- 1Windowlicker не работает на OS X
- 1Изменение ImageView по нажатию кнопки
- 0Как нарисовать таблицу как вертикальную, используя Jquery?
- 0MySQL — вставить запрос в строку подключения
- 0Заполните выпадающий список из другой таблицы MySQL — php
- 0Неверный синтаксис запроса при запросе couchdb lucene из php (с curl) нелатинскими символами
- 0angularjs не привязан к сгенерированной привязке
- 1Является ли java.nio.file.PathMatcher потоком безопасно?
- 0Импорт Geo Point (Lat, Lng) из MySQL в Elasticsearch
- 1Список файлов, начиная с папки src
- 02 вопроса на Backbone.js MVC
- 0SQL: выберите элемент в одном столбце на основе значения другого столбца.
- 1Android-адаптер для 2 источников данных
- 0Проверка JQuery — Назначение правил в качестве переменной
- 0попарный подсчет: SQL
- 1JavaScript в новом окне
- 1ResultSetMetaData получает значение по умолчанию для столбца
- 0PHP сортирует массив ассоциативных массивов по размеру элемента / размеру строки
- 0Php создать объект в конструкторе
- 0Настройте mysimpleads с помощью CakePHP
- 1Как преобразовать экземпляр пользовательского класса в кортеж
- 0Бесконечное вычисление qsort
- 0как проверить данные по тексту?
- 1Запуск действия с Intent и SetClassName
- 1Печать оператора массива
- 1Как получить 4. Среду следующего месяца как DateTime?
- 1Условно прерванная отладка
- 0Конструктор запросов — codeigniter
- 0Группировка пользователей по n группам размеров с помощью angularfire
- 0AngularJS — динамически загружать templateURL при передаче объекта в атрибут
- 0Mysql агрегированная сумма построчно [дубликаты]
- 1set_printoptions для массива numpy не работает для numpy ndarray?
- 0Получение изменений базы данных Mysql и загрузка файлов
- 0php код в случае если условие не работает должным образом
- 0шаблон ветки отображения статей с определенной даты
- 1C # Обновление метки с изображением
- 1Как узнать длину аудиозаписи в Android
- 0Создание объекта программно в ActionScript Error
- 0Статическая функция-член не может получить доступ к защищенному члену класса