I’ve been training to use object orientated programming in c++ but I keep getting this error:
1>main.obj : error LNK2005: "int WIDTH" (?WIDTH@@3HA) already defined in GameObject.obj
1>main.obj : error LNK2005: "int HEIGHT" (?HEIGHT@@3HA) already defined in GameObject.obj
1>Spaceship.obj : error LNK2005: "int WIDTH" (?WIDTH@@3HA) already defined in GameObject.obj
1>Spaceship.obj : error LNK2005: "int HEIGHT" (?HEIGHT@@3HA) already defined in GameObject.obj
1>C:Usersteddocumentsvisual studio 2010ProjectsfullSpaceDebugfullSpace.exe : fatal error LNK1169: one or more multiply defined symbols found
However to me, it seems that the entire code is written properly and the two ints are only mentioned in the Global header and all objects seem to be inheriting properly. However, like I just said, I’m a beginner in OOP so I really need an opinion : It is also worth mentioning that I am using allegro 5 to create a side shooter.
This is the code :
(main):
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5allegro_ttf.h>
#include <allegro5allegro_audio.h>
#include <allegro5allegro_acodec.h>
#include <list>
#include "GameObject.h"
#include "Spaceship.h"
#include "Globals.h"
//controls
bool keys[] = {false, false, false, false, false};
enum KEYS{UP, DOWN, LEFT, RIGHT, SPACE};
//globals
Spaceship *ship;
std::list <GameObject *> objects;
std::list <GameObject *>::iterator iter;
std::list <GameObject *>::iterator iter2;
//prototypes
//main function
int main(int argc, char **argv)
{
//shell variables
bool done = false;
bool render = false;
float gameTime = 0;
int frames = 0;
int gameFPS = 0;
//project variables
ship = new Spaceship();
ALLEGRO_BITMAP *shipImage = NULL;
ALLEGRO_BITMAP *cometImage= NULL;
ALLEGRO_BITMAP *explImage = NULL;
ALLEGRO_BITMAP *bgImage = NULL;
ALLEGRO_BITMAP *mgImage = NULL;
ALLEGRO_BITMAP *plImage = NULL;
ALLEGRO_BITMAP *mgImage2 = NULL;
ALLEGRO_BITMAP *fgImage = NULL;
ALLEGRO_BITMAP *titleImage= NULL;
ALLEGRO_BITMAP *lostImage = NULL;
//allegro variables
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer;
ALLEGRO_FONT *font18;
//initiate variables
if(!al_init())
return -1;
display = al_create_display(WIDTH, HEIGHT);
if(!display)
return -1;
//addon installation
al_install_keyboard();
al_init_image_addon();
al_init_font_addon();
al_init_ttf_addon();
al_init_primitives_addon();
al_install_audio();
al_init_acodec_addon();
//project init
font18 = al_load_font("arial.ttf", 18, 0);
al_reserve_samples(15);
bgImage = al_load_bitmap("layer1.png");
mgImage = al_load_bitmap("layer2.png");
plImage = al_load_bitmap("starMG.png");
mgImage2 = al_load_bitmap("layer3.png");
fgImage = al_load_bitmap("layer4.png");
shipImage = al_load_bitmap("spaceship.png");
al_convert_mask_to_alpha(shipImage, al_map_rgb(255, 0, 255));
cometImage = al_load_bitmap("asteroid-1-96.png");
explImage = al_load_bitmap("explosion_3_40_128.png");
titleImage = al_load_bitmap("Shooter_Title.png");
lostImage = al_load_bitmap("Shooter_Lose.png");
//object init
ship->init(shipImage);
//iter list
objects.push_back(ship);
srand(time(NULL));
//timer init and startup
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / 60);
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_start_timer(timer);
gameTime = al_current_time();
while(!done)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
//input
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = true;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = true;
break;
case ALLEGRO_KEY_UP:
keys[UP] = true;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = true;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = true;
break;
}
} else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = false;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = false;
break;
case ALLEGRO_KEY_UP:
keys[UP] = false;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = false;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = false;
break;
}
}
else if (ev.type == ALLEGRO_EVENT_TIMER)
{
render = true;
//fps
frames++;
if(al_current_time() - gameTime >= 1)
{
gameTime = al_current_time();
gameFPS = frames;
frames = 0;
}
//shipUpdate
if(keys[UP])
ship ->moveUp();
else if(keys[DOWN])
ship ->moveDown();
else
ship->resetAnim(1);
if(keys[LEFT])
ship ->moveLeft();
else if(keys[RIGHT])
ship -> moveRight();
else
ship ->resetAnim(0);
}
//render
if(render && al_is_event_queue_empty(event_queue))
{
render = false;
//begin render
for(iter = objects.begin(); iter != objects.end(); ++iter)
(*iter)->render();
//Flip Buffers
al_flip_display();
al_clear_to_color(al_map_rgb(0,0,0));
}
}
//destroy objects
//visual objects
al_destroy_bitmap(cometImage);
for(iter = objects.begin(); iter != objects.end(); ++iter)
(*iter)->destroy(shipImage);
iter = objects.erase(iter);
al_destroy_bitmap(explImage);
al_destroy_bitmap(bgImage);
al_destroy_bitmap(mgImage);
al_destroy_bitmap(fgImage);
al_destroy_bitmap(titleImage);
al_destroy_bitmap(lostImage);
//audio objects
/*
al_destroy_sample(shot);
al_destroy_sample(boom);
al_destroy_sample(song);
al_destroy_sample_instance(songInstance);
*/
//shell objects
al_destroy_font(font18);
al_destroy_timer(timer);
al_destroy_event_queue(event_queue);
al_destroy_display(display);
return 0;
}
(Globals.h):
#pragma once
int WIDTH = 1024;
int HEIGHT = 800;
enum ID{PLAYER, ENEMY, BULLET, BORDER, MISC};
enum STATES{TITLE, PLAYING, LOST};
(GameObject.h):
#pragma once
#include "Globals.h"
#include <iostream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_primitives.h>
class GameObject
{
private:
int ID;
bool alive;
bool collidable;
protected:
float x;
float y;
float velX;
float velY;
int dirX;
int dirY;
int boundX;
int boundY;
int maxFrame;
int curFrame;
int frameCount;
int frameDelay;
int frameWidth;
int frameHeight;
int animationColumns;
int animationDirection;
ALLEGRO_BITMAP *image;
public:
GameObject();
void virtual destroy(ALLEGRO_BITMAP *image);
void init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY);
void virtual update();
void virtual render();
float getX() {return x;}
float getY() {return y;}
void setX(float x) {GameObject::x = x;}
void setY(float y) {GameObject::y = y;}
int getBoundX() {return boundX;}
int getBoundY() {return boundY;}
int getID() {return ID;}
void setID(int ID) {GameObject::ID = ID;}
bool getAlive() {return alive;}
void setAlive(bool alive) {GameObject::alive = alive;}
bool getCollidable() {return collidable;}
void setCollidable(bool collidable) {GameObject::collidable = collidable;}
bool checkCollisions(GameObject *otherObject);
void virtual collided(int objectID);
bool collidableCheck();
};
(GameObject.cpp):
#include "GameObject.h"
GameObject::GameObject()
{
x = 0;
y = 0;
velX = 0;
velY = 0;
dirX = 0;
dirY = 0;
boundX = 0;
boundY = 0;
maxFrame = 0;
curFrame = 0;
frameCount = 0;
frameDelay = 0;
frameWidth = 0;
frameHeight = 0;
animationColumns = 0;
animationDirection = 0;
image = NULL;
alive = true;
collidable = true;
}
void GameObject::destroy(ALLEGRO_BITMAP *image)
{
if(image != NULL)
al_destroy_bitmap(image);
}
void GameObject::init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY)
{
GameObject::x = x;
GameObject::y = y;
GameObject::velX = velX;
GameObject::velY = velY;
GameObject::dirX = dirX;
GameObject::dirY = dirY;
GameObject::boundX = boundX;
GameObject::boundY = boundY;
}
void GameObject::update()
{
x += velX*dirX;
y += velY*dirY;
}
void GameObject::render()
{
}
bool GameObject::checkCollisions(GameObject *otherObject)
{
float oX = otherObject->getX();
float oY = otherObject->getY();
int obX = otherObject->getBoundX();
int obY = otherObject->getBoundY();
if(x + boundX > oX - obX &&
x - boundX < oX + obX &&
y + boundY > oY - obY &&
y - boundY < oY + obY
)
return true;
else
return false;
}
void GameObject::collided(int objectID)
{
}
bool GameObject::collidableCheck()
{
return alive && collidable;
}
(SpaceShip.h):
#pragma once
#include "GameObject.h"
class Spaceship : public GameObject
{
private :
int lives;
int score;
int animationRow;
public :
Spaceship();
void destroy(ALLEGRO_BITMAP *image);
void init(ALLEGRO_BITMAP *image = NULL);
void update();
void render();
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
void resetAnim(int pos);
int getLives(){return lives;}
int getScore() {return score;}
void looseLife() {lives--;}
void addPoint() {score++;}
void collide(int objectID);
};
(SpaceShip.cpp):
#include "Spaceship.h"
Spaceship::Spaceship()
{}
void Spaceship::destroy(ALLEGRO_BITMAP *image)
{
GameObject::destroy(image);
}
void Spaceship::init(ALLEGRO_BITMAP *image)
{
GameObject::init(20, 200, 6, 6, 0, 0, 10, 12);
setID(PLAYER);
setAlive(true);
lives = 3;
score = 0;
maxFrame = 3;
curFrame = 0;
frameWidth = 46;
frameHeight = 41;
animationColumns = 3;
animationDirection = 1;
animationRow = 1;
if(image != NULL)
{
Spaceship::image = image;
}
}
void Spaceship::update()
{
GameObject::update();
if(x < 0)
x=0;
else if ( x > WIDTH)
x = WIDTH;
if(y < 0)
y = 0;
else if (y > HEIGHT)
y = HEIGHT;
}
void Spaceship::render()
{
GameObject::render();
int fx = (curFrame % animationColumns) *frameWidth;
int fy = animationRow *frameHeight;
al_draw_bitmap_region(image, fx, fy, frameWidth, frameHeight,
x - frameWidth /2, y - frameHeight /2, 0);
}
void Spaceship::moveUp()
{
animationRow = 0;
dirY = -1;
}
void Spaceship::moveDown()
{
animationRow = 2;
dirY = 1;
}
void Spaceship::moveLeft()
{
curFrame = 2;
dirX = -1;
}
void Spaceship::moveRight()
{
curFrame = 1;
dirX = 1;
}
void Spaceship::resetAnim(int pos)
{
if(pos == 1)
{
animationRow = 1;
dirY = 0;
}
else
{
curFrame = 0;
dirX = 0;
}
}
void Spaceship::collide(int objectID)
{
if(objectID == ENEMY)
lives--;
}
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||||||||||||||||||||||
1 |
||||||||||||||||||||||||
05.07.2013, 09:51. Показов 4503. Ответов 16 Метки нет (Все метки)
Доброго всем времени суток! Никак не могу разобраться в чём дело… Помогите пожалуйста!
Get_String_Getche.h
Very_Long_Number.h
Get_String_Getche.cpp
Very_Long_Number.cpp
Выдаёт вот это: fatal error LNK1169: one or more multiply defined symbols found Добавлено через 18 минут
__________________
0 |
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
08.07.2013, 11:17 [ТС] |
2 |
Help please! Добавлено через 22 часа 21 минуту Добавлено через 1 час 23 минуты Добавлено через 10 часов 12 минут
0 |
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
09.07.2013, 06:30 |
3 |
|||
Это из-за:
в Very_Long_Number.h. Он подключается в двух файлах (main() и Very_Long_Number.cpp), отсюда множетсвенное определение.
1 |
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
09.07.2013, 06:43 [ТС] |
4 |
Спасибо… кажется разобрался.
0 |
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
09.07.2013, 06:53 |
5 |
|||
Только как от этого избавиться (в студии) я не занаю, кроме как убрать из файлов все объявленя/определения SZ и прописать в Get_String_Getche.h:
Добавлено через 2 минуты
0 |
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
09.07.2013, 07:06 [ТС] |
6 |
|||
Я перенёс
в «stdafx.h» и проблема решена.
0 |
Tulosba |
09.07.2013, 07:33
|
Не по теме:
И ещё, рекомендуется using namespace std; помещать, в файле, после всех инклудов. Рекомендуется не использовать данную запись в принципе.
0 |
alsav22 |
09.07.2013, 07:44
|
Не по теме:
Рекомендуется не использовать данную запись в принципе. В заголовочных файлах.
0 |
alsav22 |
09.07.2013, 07:54
|
0 |
alsav22 5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
||||
09.07.2013, 07:59 |
10 |
|||
Я перенёс
в «stdafx.h» и проблема решена. Откуда что перенесли? Не пойму, как это может помочь, если stdafx.h тоже подключен к нескольким .cpp?
0 |
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
09.07.2013, 08:04 [ТС] |
11 |
|||
— кажется эта директива служит защитой от множественного включения
0 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
09.07.2013, 08:06 |
12 |
А что конкретно перенесли? Откуда?
0 |
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||
09.07.2013, 08:10 [ТС] |
13 |
|||
— удалил из файла с main(), и из «Very_Long_Number.cpp», и записал в «stdafx.h»
0 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
09.07.2013, 08:16 |
14 |
У меня ошибка остаётся. Не понятно, почему у вас нет. Весь проект может выложить?
0 |
Асурус 2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
||||||||||||||||||||||||
09.07.2013, 08:27 [ТС] |
15 |
|||||||||||||||||||||||
У меня там много и других ошибок… вот проект:
stdafx.h
Very_Long_Number.h
Class_Very_Long_Number.cpp
Get_String_Getche.cpp
Very_Long_Number.cpp
0 |
5493 / 4888 / 831 Регистрация: 04.06.2011 Сообщений: 13,587 |
|
09.07.2013, 08:42 |
16 |
вот проект: Я имел ввиду файлы студии. Добавлено через 54 секунды
У меня там много и других ошибок… Может до этой просто не доходит? Добавлено через 6 минут
0 |
2 / 2 / 2 Регистрация: 27.07.2012 Сообщений: 40 |
|
09.07.2013, 08:58 [ТС] |
17 |
Не, теперь всё в норме, я закоментировал вызовы функций с ошибками, всё выполняется. Добавлено через 1 минуту Добавлено через 7 минут
0 |
Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 07.06.09 11:54 | ||
Оценка: |
При компиляции происходят ошибки:
1 — error LNK2005: _assetType already defined in customer.obj
2 — fatal error LNK1169: one or more multiply defined symbols found
Погуглив я понял, что компилятор вставляет 2 раз вот это
const char* assetType[] = {"apartment", "shop", "house"};
но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Почему тогда происходит ошибка и как ее исправить?
Большое спасибо.
//main.c
#include "customer.h"
void main()
{
}
//customer.h
#ifndef _CUSTOMER_H_
#define _CUSTOMER_H_
const char* assetType[] = {"apartment", "shop", "house"};
void func();
#endif
//customer.c
#include "customer.h"
void func()
{
int i;
}
Re: Почему происходит multiply defined symbols
|
От: |
Caracrist |
https://1pwd.org/ |
Дата: | 07.06.09 12:10 | ||
Оценка: |
-2 |
Re[2]: Почему происходит multiply defined symbols
|
От: |
Caracrist |
https://1pwd.org/ |
Дата: | 07.06.09 12:26 | ||
Оценка: |
+1 |
Здравствуйте, Caracrist, Вы писали:
C>this ?
C>
C>#pragma once
C>
это я прогнал
missing static…
static const char* assetType[] = {"apartment", "shop", "house"};
Re: Почему происходит multiply defined symbols
|
От: |
andrey.desman |
|
Дата: | 07.06.09 12:45 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Да, один раз, но в каждую единицу трансляции (файл .c / .cpp).
Этот так называемый include guard помогает в ситуации, когда заголовок (файл .h) включается два или более раза в одну единицу трансляции.
TA>Почему тогда происходит ошибка и как ее исправить?
Так как символ глобальный, то он «виден» и из других единиц трансляции. Но так как заголовок включен в оба сишника, то создается два символа с одним и тем же именем, чего линкер очень не любит.
Либо добавь «static», тогда в каждом сишнике будет своя копия этого массива и конфликта имен не будет.
Либо, определение в какой-нибудь один сишник, а в заголовок только объявление. Тогда будет существовать лишь одна копия этого массива.
Re: Почему происходит multiply defined symbols
|
От: |
Alexey F |
|
Дата: | 07.06.09 12:51 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>const char* assetType[] = {"apartment", "shop", "house"};
TA>
В дополнение к данным выше ответам:
const char* const assetType[] = {"apartment", "shop", "house"};
Так тоже будет работать (подразумевается внутреннее связывание).
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Верно. По одному разу в каждый файл, который подключил customer.h.
P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
Re[2]: Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 07.06.09 20:01 | ||
Оценка: |
Здравствуйте, andrey.desman, Вы писали:
AD>Здравствуйте, TheAteist, Вы писали:
TA>>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
AD>Да, один раз, но в каждую единицу трансляции (файл .c / .cpp).
AD>Этот так называемый include guard помогает в ситуации, когда заголовок (файл .h) включается два или более раза в одну единицу трансляции.
1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
TA>>Почему тогда происходит ошибка и как ее исправить?
AD>Так как символ глобальный, то он «виден» и из других единиц трансляции. Но так как заголовок включен в оба сишника, то создается два символа с одним и тем же именем, чего линкер очень не любит.
AD>Либо добавь «static», тогда в каждом сишнике будет своя копия этого массива и конфликта имен не будет.
Своя копия означает
AD>Либо, определение в какой-нибудь один сишник, а в заголовок только объявление. Тогда будет существовать лишь одна копия этого массива.
Re[2]: Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 07.06.09 20:02 | ||
Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, TheAteist, Вы писали:
TA>>При компиляции происходят ошибки:
TA>>1 — error LNK2005: _assetType already defined in customer.obj
TA>>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>>
TA>>const char* assetType[] = {"apartment", "shop", "house"};
TA>>
AF>В дополнение к данным выше ответам:
AF>
AF>const char* const assetType[] = {"apartment", "shop", "house"};
AF>
AF>Так тоже будет работать (подразумевается внутреннее связывание).
TA>>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
AF>Верно. По одному разу в каждый файл, который подключил customer.h.
1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
AF>P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
AF>в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
Re[3]: Почему происходит multiply defined symbols
|
От: |
Kirikaza |
kirikaza.ru |
Дата: | 07.06.09 20:35 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
Пусть есть файл x.h:
#ifndef X_H
#define X_H
...
#endif
Если файл x.h вставлен дважды в некий C-файл
#include "x.h"
#include "x.h"
то получается вот так:
#ifndef X_H
#define X_H
...
#endif
#ifndef X_H
#define X_H
...
#endif
При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
Re[3]: Почему происходит multiply defined symbols
|
От: |
Alexey F |
|
Дата: | 07.06.09 20:46 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл
В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
Re[4]: Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 07.06.09 21:19 | ||
Оценка: |
Здравствуйте, Kirikaza, Вы писали:
K>Здравствуйте, TheAteist, Вы писали:
TA>>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
K>#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
K>Пусть есть файл x.h:
K>
#ifndef X_H
K>#define X_H
K>...
K>#endif
K>
K>Если файл x.h вставлен дважды в некий C-файл
K>
#include "x.h"
K>#include "x.h"
K>то получается вот так:
K>
#ifndef X_H
K>#define X_H
K>...
K>#endif
K>#ifndef X_H
K>#define X_H
K>...
K>#endif
K>При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
K>Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
K>В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
K>Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
K>P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
Re[4]: Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 07.06.09 21:21 | ||
Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>Здравствуйте, TheAteist, Вы писали:
TA>>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
AF>include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
TA>>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
AF>Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл
AF>В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
AF>P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
Re[5]: Почему происходит multiply defined symbols
|
От: |
Alexey F |
|
Дата: | 07.06.09 22:36 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
[offtop]
Зачем дублируете ответы? И оверквотинг лишний.
[/offtop]
TA>Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
Здесь разные вещи. С помощью typedef enum Вы определяете тип.
А
const char* assetType[] = {"apartment", "shop", "house"};
определяет переменную, которая уже имеет по-умолчанию внешнее связывание, т.е. учавствует при линковке. Соответственно, получаются две переменные с одним и тем же именем, определённые в двух разных файлах трансляции. Какую прикажете выбирать линкеру?
Иллюстрация более наглядного случая (чтобы было понятно, почему линковщик не имеет право плюнуть на это и выбрать одно из определений):
// 1.cpp
int val = 0; // фактически, эта строка могла быть в h-файле
// 2.cpp
int val = 42; // фактически, эта строка могла быть в h-файле
// 3.cpp
extern int val;
...
printf ( "%d", val ); // Ой! А какая val?
P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Re: Почему происходит multiply defined symbols
|
От: |
LaptevVV |
|
Дата: | 08.06.09 07:29 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>const char* assetType[] = {"apartment", "shop", "house"};
TA>
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
TA>Почему тогда происходит ошибка и как ее исправить?
TA>Большое спасибо.
Я обычно делаю так:
1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
2. Пишу variable.h, в котором делаю ОБЪЯВЛЕНИЯ
extern переменная/константа;
3. К единицам трансляции подключаю variable.h
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Почему происходит multiply defined symbols
|
От: |
рыбак |
|
Дата: | 08.06.09 10:49 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
#ifndef (или #pragma once) защищает от двойного включения заголовка (.h) в одну единицу компиляции (.cpp). То есть для удачной компиляции.
У тебя же ошибка линковки. Это когда в двух разных единицах компиляции (.cpp) получился одинаковый символ.
Re[2]: Почему происходит multiply defined symbols
|
От: | Аноним | |
Дата: | 08.06.09 11:15 | ||
Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Я обычно делаю так:
LVV>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Re[5]: Почему происходит multiply defined symbols
|
От: |
Юрий Жмеренецкий |
ICQ 380412032 |
Дата: | 08.06.09 11:40 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>Я не понял почему только на массив все «крики», а не, скажем на «typedef enum{eBuy, eSell, eRent} assetAction;» который у меня определяется под массивом.
Это enumerator-definition, а для таких (и некоторых других) определений есть список условий, при соблюдении которых уникальность (определения в пределах программы) не является обязательной (3.2/5).
TA>Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
В приведенном выше коде в файле ‘customer.h’ находится объявление функции (func), а не определение.
PS: Поищи по «One definition rule», здесь это неоднократно обсуждалось.
Re[6]: Почему происходит multiply defined symbols
|
От: |
TheAteist |
|
Дата: | 08.06.09 17:28 | ||
Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Кажется я понял
Значит премерно вот так получается, да?
//main.obj
const char* assetType[] = {"apartment", "shop", "house"};
void func();
void main()
{
}
//customer.obj
const char* assetType[] = {"apartment", "shop", "house"};
void func();
void func()
{
int i;
}
Re[3]: Почему происходит multiply defined symbols
|
От: |
LaptevVV |
|
Дата: | 09.06.09 05:18 | ||
Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, LaptevVV, Вы писали:
LVV>>Я обычно делаю так:
LVV>>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А>А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
Каждый класс — это class.h и class.cpp
Можно в class.h собрать несколько классов, но лучше разделить.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Почему происходит multiply defined symbols
|
От: | Аноним | |
Дата: | 09.06.09 11:23 | ||
Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, LaptevVV, Вы писали:
LVV>Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
LVV>Каждый класс — это class.h и class.cpp
LVV>Можно в class.h собрать несколько классов, но лучше разделить.
А почему лучше их разделить и почему нельзя эти рассуждения применить к общим переменным?
- Переместить
- Удалить
- Выделить ветку
Пока на собственное сообщение не было ответов, его можно удалить.
Содержание
- Fatal error lnk1169 one or more multiply defined symbols found
- Asked by:
- Question
- All replies
- Fatal error lnk1169 one or more multiply defined symbols found
- Asked by:
- Question
- All replies
- Fatal error lnk1169 one or more multiply defined symbols found
- Fatal error lnk1169 one or more multiply defined symbols found
- Answered by:
- Question
- Fatal error lnk1169 one or more multiply defined symbols found
Fatal error lnk1169 one or more multiply defined symbols found
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Asked by:
Question
fatal error LNK1169: one or more multiply defined symbols found
How can i fix this error?
Welcome to MSDN forum.
>> Fatal error LNK1169
## This error is preceded by error LNK2005. Generally, this error means you have broken the one definition rule, which allows only one definition for any used template, function, type, or object in a given object file, and only one definition across the entire executable for externally visible objects or functions.
Do you meet this error when you are running test project? And does your project build/debug well without any error?
According to the official document, You could refer to below possible causes and for solutions please refer to this link Possible causes and solutions.
(1) Check if one of your header file defines a variable and maybe include this header file in more than one source file in your project.
(2) This error can occur when a header file defines a function that isn’t inline. If you include this header file in more than one source file, you get multiple definitions of the function in the executable.
(3) This error can also occur if you define member functions outside the class declaration in a header file.
(4) This error can occur if you link more than one version of the standard library or CRT.
(5) This error can occur if you mix use of static and dynamic libraries when you use the /clr option
(6) This error can occur if the symbol is a packaged function (created by compiling with /Gy ) and it was included in more than one file, but was changed between compilations.
(7) This error can occur if the symbol is defined differently in two member objects in different libraries, and both member objects are used. One way to fix this issue when the libraries are statically linked is to use the member object from only one library, and include that library first on the linker command line.
(8) This error can occur if an extern const variable is defined twice, and has a different value in each definition.
(9) This error can occur if you use uuid.lib in combination with other .lib files that define GUIDs (for example, oledb.lib and adsiid.lib).
There are some similar issues and maybe helpful.
Источник
Fatal error lnk1169 one or more multiply defined symbols found
This forum has migrated to Microsoft Q&A. Visit Microsoft Q&A to post new questions.
Asked by:
Question
fatal error LNK1169: one or more multiply defined symbols found
How can i fix this error?
Welcome to MSDN forum.
>> Fatal error LNK1169
## This error is preceded by error LNK2005. Generally, this error means you have broken the one definition rule, which allows only one definition for any used template, function, type, or object in a given object file, and only one definition across the entire executable for externally visible objects or functions.
Do you meet this error when you are running test project? And does your project build/debug well without any error?
According to the official document, You could refer to below possible causes and for solutions please refer to this link Possible causes and solutions.
(1) Check if one of your header file defines a variable and maybe include this header file in more than one source file in your project.
(2) This error can occur when a header file defines a function that isn’t inline. If you include this header file in more than one source file, you get multiple definitions of the function in the executable.
(3) This error can also occur if you define member functions outside the class declaration in a header file.
(4) This error can occur if you link more than one version of the standard library or CRT.
(5) This error can occur if you mix use of static and dynamic libraries when you use the /clr option
(6) This error can occur if the symbol is a packaged function (created by compiling with /Gy ) and it was included in more than one file, but was changed between compilations.
(7) This error can occur if the symbol is defined differently in two member objects in different libraries, and both member objects are used. One way to fix this issue when the libraries are statically linked is to use the member object from only one library, and include that library first on the linker command line.
(8) This error can occur if an extern const variable is defined twice, and has a different value in each definition.
(9) This error can occur if you use uuid.lib in combination with other .lib files that define GUIDs (for example, oledb.lib and adsiid.lib).
There are some similar issues and maybe helpful.
Источник
Fatal error lnk1169 one or more multiply defined symbols found
Write your question here. Hi, it is me again. I am getting this error and cannot figure out what I am doing wrong. It is in visual studios 2013 again BTW.
[#include «stdafx.h» // Precompiled header
#include «iostream» // Input and output stream
using namespace std; // Meaning you don’t have to put std:: before cout Last edited on
can you use code tags please?
for example, you prototype:
int squareIntegers();
but you call it like this:
squareIntegers(22)
you also do not need prototype declarations if you’re implementing them before you call them.
i.e. delete these:
why are you doing calculations and then return zero?
edit:
you also do not need this either:
are wrong, and not even needed.
I did it because I cannot return both answer1 and answer2 twice.
You need to read that link i pasted on functions.
So, I read it but and why are
[int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();], wrong. They are function prototypes.
Also, I get an error saying to include «stdafx.h» if I don’t include it.
Also, for squareIntegers(22), I used this in my last program, and it worked fine. I have no idea what else could be the issue.
They are function prototypes.
Yes they are, but they don’t match your functions!
This prototype:
You’re telling the compiler about a different function. This one takes an integer and returns an integer.
This issue becomes apparent when you move your functions implementations below your main function:
(10): error C2660: ‘squareIntegers’ : function does not take 1 arguments
(11): error C2660: ‘squareDouble’ : function does not take 1 arguments
(12): error C2660: ‘squareFloat’ : function does not take 2 arguments
Because your prototypes should be:
Okay, thanks for that, but I still have this error: «fatal error LNK1169: one or more multiply defined symbols found.»
Does this mean in my squareFloat function, I need to make a struct, return the struct name? Will that get rid of this error?
Источник
Fatal error lnk1169 one or more multiply defined symbols found
Answered by:
Question
I’ve read other posts about this and usually it’s caused by accidently adding two or more copies of the same source code to the project.
I have three source code files and I can’t identify which symbol is ‘multiply defined’. This link error only occured when I started building the release version, it was fine on debug, so I have no idea when the problem started.
Here is the full error report:
—— Rebuild All started: Project: solver, Configuration: Release Win32 ——
Deleting intermediate and output files for project ‘solver’, configuration ‘Release|Win32’
.solver.cpp(240) : warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data
.solver.cpp(269) : warning C4305: ‘=’ : truncation from ‘double’ to ‘float’
.solver.cpp(271) : warning C4244: ‘=’ : conversion from ‘double’ to ‘float’, possible loss of data
warning C4727: PCH named c:documents and settingsusermy documentsvisual studio 2005projectssolversolverreleasesolver.pch with same timestamp found in c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleasestdafx.obj and c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleasesolver.obj. Using first PCH.
stdafx.obj : error LNK2005: ___@@_PchSym_@00@UwlxfnvmghLzmwLhvggrmthUfhviUnbLwlxfnvmghUerhfzoLhgfwrlLCAAFUkilqvxghUhloeviUhloeviUivovzhvUhgwzucOlyq@ already defined in solver.obj
C:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolverReleasesolver.exe : fatal error LNK1169: one or more multiply defined symbols found
Build log was saved at «file://c:Documents and SettingsuserMy DocumentsVisual Studio 2005ProjectssolversolverReleaseBuildLog.htm»
solver — 2 error(s), 3 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========
Источник
Fatal error lnk1169 one or more multiply defined symbols found
При компиляции происходят ошибки:
1 — error LNK2005: _assetType already defined in customer.obj
2 — fatal error LNK1169: one or more multiply defined symbols found
Погуглив я понял, что компилятор вставляет 2 раз вот это
но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Почему тогда происходит ошибка и как ее исправить?
Большое спасибо.
|
От: | Caracrist | https://1pwd.org/ |
Дата: | 07.06.09 12:10 | ||
Оценка: | -2 |
|
От: | Caracrist | https://1pwd.org/ |
Дата: | 07.06.09 12:26 | ||
Оценка: | +1 |
Здравствуйте, Caracrist, Вы писали:
C>this ?
C>
это я прогнал
|
От: | andrey.desman |
Дата: | 07.06.09 12:45 | |
Оценка: |
|
От: | Alexey F |
Дата: | 07.06.09 12:51 | |
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
В дополнение к данным выше ответам:
Так тоже будет работать (подразумевается внутреннее связывание).
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
Верно. По одному разу в каждый файл, который подключил customer.h.
P.S. Если нет желания делать массив константным или внутренним для каждой единицы трансляции, то только так:
в заголовке его объявляем с extern, а определяем в отдельном .c/.cpp файле
|
От: | TheAteist |
Дата: | 07.06.09 20:01 | |
Оценка: |
|
От: | TheAteist |
Дата: | 07.06.09 20:02 | |
Оценка: |
|
От: | Kirikaza | kirikaza.ru |
Дата: | 07.06.09 20:35 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
#include «x.h» лучше рассматривать как «вставить в этом месте содержимое файла x.h».
Пусть есть файл x.h:
Если файл x.h вставлен дважды в некий C-файл
то получается вот так:
При этом первый #ifndef сработает, т.к. X_H ещё не определена, и определит X_H. А второй #ifndef не сработает, т.к. X_H уже определена.
Когда происходит компиляция, препроцессор берёт C-файл выполняет вот эту подстановку и оставляет код внутри первого #if и выкидывает внутри второго. Затем полученный код отдаётся компилятору, который компилирует и получает объектный файл. Затем берётся второй C-файл и для него независимо от первого C-файла процедура повторяется заново (т.е. в самом начале обработки препроцессором второго C-файла X_H никем не была определена). Когда все объектные файлы получены, они все линкуются (связываются) в один.
В твоём случае H-файл включается по разу в каждый подключающий его C-файл. Объектные файлы получаются с копиями того массива, но компилятор при создании каждого из них об этом не знает. А вот линковщик (linker) видит две вещи с одним именем в одной глобальной области и пугается, т.к. для обеих из них есть определение.
Т.е. H-файлы сами по себе непосредственно не обрабатываются. Всё исходит от C-файлов. Ну а что делать — тебе уже сказали.
P.S.: На самом деле компиляторы данный процесс обычно оптимизируют, но поведение такое сохраняют.
|
От: | Alexey F |
Дата: | 07.06.09 20:46 | |
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
include-guard (те самые #ifndef/#define/#endif) нужны для других целей. А, именно, для предотвращения включения текста включаемого файла дважды в одну и ту же единицу трансляции. Такое может произойти, например, когда файл X.h включает файл Y.h, а потом включает файл Z.h, который, в свою очередь, снова подключает Y.h. Без include-guard’ов получили бы множество ошибок переопределения.
TA>2)И если подключается по одной копии в каждый сишник, так разве #ifndef не был придуман, чтоб сэкономить место на диске и подключать только один раз?
Сэкономить место на диске? Нет, скорее сэкономить время и нервы программиста, избавляя его от перебивания одинаковых строк из файла в файл
В Вашем случае решение ситуации в смене связывания объявляемому массиву. Как это сделать — уже описали выше (static, const, extern).
P.S. Ещё безымянные namespace могут решить проблему, но по мне лучше уж const или вынос определения в отдельную единицу трансляции.
|
От: | TheAteist |
Дата: | 07.06.09 21:19 | |
Оценка: |
|
От: | TheAteist |
Дата: | 07.06.09 21:21 | |
Оценка: |
|
От: | Alexey F |
Дата: | 07.06.09 22:36 | |
Оценка: |
Здравствуйте, TheAteist, Вы писали:
[offtop]
Зачем дублируете ответы? И оверквотинг лишний.
[/offtop]
TA>Это я понял. Я не понял почему только на массив все «крики», а не, скажем на «typedef enum assetAction;» который у меня определяется под массивом. Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
Здесь разные вещи. С помощью typedef enum Вы определяете тип.
А
определяет переменную, которая уже имеет по-умолчанию внешнее связывание, т.е. учавствует при линковке. Соответственно, получаются две переменные с одним и тем же именем, определённые в двух разных файлах трансляции. Какую прикажете выбирать линкеру?
Иллюстрация более наглядного случая (чтобы было понятно, почему линковщик не имеет право плюнуть на это и выбрать одно из определений):
P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
|
От: | LaptevVV |
Дата: | 08.06.09 07:29 | |
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>При компиляции происходят ошибки:
TA>1 — error LNK2005: _assetType already defined in customer.obj
TA>2 — fatal error LNK1169: one or more multiply defined symbols found
TA>Погуглив я понял, что компилятор вставляет 2 раз вот это
TA>
TA>но я же добавил в customer.h #ifndef, значит «const char* assetType» должен добавлсят только 1 раз
TA>Почему тогда происходит ошибка и как ее исправить?
TA>Большое спасибо.
Я обычно делаю так:
1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
2. Пишу variable.h, в котором делаю ОБЪЯВЛЕНИЯ
3. К единицам трансляции подключаю variable.h
|
От: | рыбак |
Дата: | 08.06.09 10:49 | |
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>1)Так если в любом случае подключается по одной копии в каждый сишник, который подключил customer.h, так зачем тогда нужен #ifndef? Или что-то не так понял?
#ifndef (или #pragma once) защищает от двойного включения заголовка (.h) в одну единицу компиляции (.cpp). То есть для удачной компиляции.
У тебя же ошибка линковки. Это когда в двух разных единицах компиляции (.cpp) получился одинаковый символ.
|
От: | Аноним |
Дата: | 08.06.09 11:15 | |
Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Я обычно делаю так:
LVV>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
|
От: | Юрий Жмеренецкий | ICQ 380412032 |
Дата: | 08.06.09 11:40 | ||
Оценка: |
Здравствуйте, TheAteist, Вы писали:
TA>Я не понял почему только на массив все «крики», а не, скажем на «typedef enum assetAction;» который у меня определяется под массивом.
Это enumerator-definition, а для таких (и некоторых других) определений есть список условий, при соблюдении которых уникальность (определения в пределах программы) не является обязательной (3.2/5).
TA>Или на определений функций, которые и они находятся в том же customer.h и все в #ifndef.
В приведенном выше коде в файле ‘customer.h’ находится объявление функции (func), а не определение.
PS: Поищи по «One definition rule», здесь это неоднократно обсуждалось.
|
От: | TheAteist |
Дата: | 08.06.09 17:28 | |
Оценка: |
Здравствуйте, Alexey F, Вы писали:
AF>P.S. Даже если тела Ваших массивов одинаковы, для линкера — это две переменных с одним и тем же именем.
Кажется я понял
Значит премерно вот так получается, да?
|
От: | LaptevVV |
Дата: | 09.06.09 05:18 | |
Оценка: |
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, LaptevVV, Вы писали:
LVV>>Я обычно делаю так:
LVV>>1. Все переменные и константы, которые мне нужны в нескольких единицах трансляции, выношу в отдельный файл вроде variable.cpp
А>А все классы, которые нужны в нескольких единицах трансляции выносишь в файл вроде class.cpp? Одно непонятно, откуда при таком подходе появляется больше одной единицы трансляции.
Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
Каждый класс — это class.h и class.cpp
Можно в class.h собрать несколько классов, но лучше разделить.
|
От: | Аноним |
Дата: | 09.06.09 11:23 | |
Оценка: |
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Аноним, Вы писали:
А>>Здравствуйте, LaptevVV, Вы писали:
LVV>Зачем-же? Речь идет не о классах, а об общих переменных. Если они требуются, конечно.
LVV>Каждый класс — это class.h и class.cpp
LVV>Можно в class.h собрать несколько классов, но лучше разделить.
А почему лучше их разделить и почему нельзя эти рассуждения применить к общим переменным?
Источник
Я тренировался использовать объектно-ориентированное программирование в C ++, но я продолжаю получать эту ошибку:
1>main.obj : error LNK2005: "int WIDTH" (?WIDTH@@3HA) already defined in GameObject.obj
1>main.obj : error LNK2005: "int HEIGHT" (?HEIGHT@@3HA) already defined in GameObject.obj
1>Spaceship.obj : error LNK2005: "int WIDTH" (?WIDTH@@3HA) already defined in GameObject.obj
1>Spaceship.obj : error LNK2005: "int HEIGHT" (?HEIGHT@@3HA) already defined in GameObject.obj
1>C:Usersteddocumentsvisual studio 2010ProjectsfullSpaceDebugfullSpace.exe : fatal error LNK1169: one or more multiply defined symbols found
Однако, мне кажется, что весь код написан правильно, и эти два целых числа упоминаются только в глобальном заголовке, и все объекты, похоже, наследуются правильно. Однако, как я только что сказал, я новичок в ООП, поэтому мне действительно нужно мнение: Стоит также упомянуть, что я использую allegro 5 для создания бокового шутера.
Это код:
(главный):
#include <allegro5/allegro.h>
#include <allegro5/allegro_image.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>
#include <allegro5allegro_ttf.h>
#include <allegro5allegro_audio.h>
#include <allegro5allegro_acodec.h>
#include <list>#include "GameObject.h"#include "Spaceship.h"#include "Globals.h"//controls
bool keys[] = {false, false, false, false, false};
enum KEYS{UP, DOWN, LEFT, RIGHT, SPACE};
//globals
Spaceship *ship;
std::list <GameObject *> objects;
std::list <GameObject *>::iterator iter;
std::list <GameObject *>::iterator iter2;//prototypes//main function
int main(int argc, char **argv)
{
//shell variables
bool done = false;
bool render = false;
float gameTime = 0;
int frames = 0;
int gameFPS = 0;
//project variables
ship = new Spaceship();ALLEGRO_BITMAP *shipImage = NULL;
ALLEGRO_BITMAP *cometImage= NULL;
ALLEGRO_BITMAP *explImage = NULL;
ALLEGRO_BITMAP *bgImage = NULL;
ALLEGRO_BITMAP *mgImage = NULL;
ALLEGRO_BITMAP *plImage = NULL;
ALLEGRO_BITMAP *mgImage2 = NULL;
ALLEGRO_BITMAP *fgImage = NULL;
ALLEGRO_BITMAP *titleImage= NULL;
ALLEGRO_BITMAP *lostImage = NULL;//allegro variables
ALLEGRO_DISPLAY *display = NULL;
ALLEGRO_EVENT_QUEUE *event_queue = NULL;
ALLEGRO_TIMER *timer;
ALLEGRO_FONT *font18;//initiate variables
if(!al_init())
return -1;
display = al_create_display(WIDTH, HEIGHT);
if(!display)
return -1;
//addon installation
al_install_keyboard();
al_init_image_addon();
al_init_font_addon();
al_init_ttf_addon();
al_init_primitives_addon();
al_install_audio();
al_init_acodec_addon();
//project init
font18 = al_load_font("arial.ttf", 18, 0);
al_reserve_samples(15);bgImage = al_load_bitmap("layer1.png");
mgImage = al_load_bitmap("layer2.png");
plImage = al_load_bitmap("starMG.png");
mgImage2 = al_load_bitmap("layer3.png");
fgImage = al_load_bitmap("layer4.png");shipImage = al_load_bitmap("spaceship.png");
al_convert_mask_to_alpha(shipImage, al_map_rgb(255, 0, 255));cometImage = al_load_bitmap("asteroid-1-96.png");
explImage = al_load_bitmap("explosion_3_40_128.png");
titleImage = al_load_bitmap("Shooter_Title.png");
lostImage = al_load_bitmap("Shooter_Lose.png");//object init
ship->init(shipImage);//iter list
objects.push_back(ship);srand(time(NULL));
//timer init and startup
event_queue = al_create_event_queue();
timer = al_create_timer(1.0 / 60);
al_register_event_source(event_queue, al_get_timer_event_source(timer));
al_register_event_source(event_queue, al_get_keyboard_event_source());
al_start_timer(timer);
gameTime = al_current_time();
while(!done)
{
ALLEGRO_EVENT ev;
al_wait_for_event(event_queue, &ev);
//input
if(ev.type == ALLEGRO_EVENT_KEY_DOWN)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = true;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = true;
break;
case ALLEGRO_KEY_UP:
keys[UP] = true;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = true;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = true;
break;}
} else if(ev.type == ALLEGRO_EVENT_KEY_UP)
{
switch(ev.keyboard.keycode)
{
case ALLEGRO_KEY_ESCAPE:
done = true;
break;
case ALLEGRO_KEY_LEFT:
keys[LEFT] = false;
break;
case ALLEGRO_KEY_RIGHT:
keys[RIGHT] = false;
break;
case ALLEGRO_KEY_UP:
keys[UP] = false;
break;
case ALLEGRO_KEY_DOWN:
keys[DOWN] = false;
break;
case ALLEGRO_KEY_SPACE:
keys[SPACE] = false;
break;
}
}else if (ev.type == ALLEGRO_EVENT_TIMER)
{
render = true;
//fps
frames++;
if(al_current_time() - gameTime >= 1)
{
gameTime = al_current_time();
gameFPS = frames;
frames = 0;
}
//shipUpdate
if(keys[UP])
ship ->moveUp();
else if(keys[DOWN])
ship ->moveDown();
else
ship->resetAnim(1);
if(keys[LEFT])
ship ->moveLeft();
else if(keys[RIGHT])
ship -> moveRight();
else
ship ->resetAnim(0);
}
//render
if(render && al_is_event_queue_empty(event_queue))
{
render = false;
//begin render
for(iter = objects.begin(); iter != objects.end(); ++iter)
(*iter)->render();//Flip Buffers
al_flip_display();
al_clear_to_color(al_map_rgb(0,0,0));
}
}
//destroy objects//visual objects
al_destroy_bitmap(cometImage);
for(iter = objects.begin(); iter != objects.end(); ++iter)
(*iter)->destroy(shipImage);
iter = objects.erase(iter);
al_destroy_bitmap(explImage);
al_destroy_bitmap(bgImage);
al_destroy_bitmap(mgImage);
al_destroy_bitmap(fgImage);
al_destroy_bitmap(titleImage);
al_destroy_bitmap(lostImage);
//audio objects
/*
al_destroy_sample(shot);
al_destroy_sample(boom);
al_destroy_sample(song);
al_destroy_sample_instance(songInstance);
*///shell objects
al_destroy_font(font18);
al_destroy_timer(timer);
al_destroy_event_queue(event_queue);
al_destroy_display(display);
return 0;
}
(Globals.h):
#pragma once
int WIDTH = 1024;
int HEIGHT = 800;
enum ID{PLAYER, ENEMY, BULLET, BORDER, MISC};
enum STATES{TITLE, PLAYING, LOST};
(GameObject.h):
#pragma once#include "Globals.h"#include <iostream>
#include <allegro5/allegro5.h>
#include <allegro5/allegro_primitives.h>class GameObject
{
private:
int ID;
bool alive;
bool collidable;
protected:
float x;
float y;
float velX;
float velY;
int dirX;
int dirY;
int boundX;
int boundY;
int maxFrame;
int curFrame;
int frameCount;
int frameDelay;
int frameWidth;
int frameHeight;
int animationColumns;
int animationDirection;
ALLEGRO_BITMAP *image;
public:
GameObject();
void virtual destroy(ALLEGRO_BITMAP *image);
void init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY);
void virtual update();
void virtual render();
float getX() {return x;}
float getY() {return y;}
void setX(float x) {GameObject::x = x;}
void setY(float y) {GameObject::y = y;}
int getBoundX() {return boundX;}
int getBoundY() {return boundY;}
int getID() {return ID;}
void setID(int ID) {GameObject::ID = ID;}
bool getAlive() {return alive;}
void setAlive(bool alive) {GameObject::alive = alive;}
bool getCollidable() {return collidable;}
void setCollidable(bool collidable) {GameObject::collidable = collidable;}
bool checkCollisions(GameObject *otherObject);
void virtual collided(int objectID);
bool collidableCheck();
};
(GameObject.cpp):
#include "GameObject.h"
GameObject::GameObject()
{
x = 0;
y = 0;
velX = 0;
velY = 0;
dirX = 0;
dirY = 0;
boundX = 0;
boundY = 0;
maxFrame = 0;
curFrame = 0;
frameCount = 0;
frameDelay = 0;
frameWidth = 0;
frameHeight = 0;
animationColumns = 0;
animationDirection = 0;
image = NULL;
alive = true;
collidable = true;
}
void GameObject::destroy(ALLEGRO_BITMAP *image)
{
if(image != NULL)
al_destroy_bitmap(image);
}
void GameObject::init(float x, float y, float velX, float velY, int dirX, int dirY, int boundX, int boundY)
{
GameObject::x = x;
GameObject::y = y;
GameObject::velX = velX;
GameObject::velY = velY;
GameObject::dirX = dirX;
GameObject::dirY = dirY;
GameObject::boundX = boundX;
GameObject::boundY = boundY;
}
void GameObject::update()
{
x += velX*dirX;
y += velY*dirY;
}
void GameObject::render()
{
}
bool GameObject::checkCollisions(GameObject *otherObject)
{
float oX = otherObject->getX();
float oY = otherObject->getY();
int obX = otherObject->getBoundX();
int obY = otherObject->getBoundY();
if(x + boundX > oX - obX &&
x - boundX < oX + obX &&
y + boundY > oY - obY &&
y - boundY < oY + obY
)
return true;
else
return false;
}
void GameObject::collided(int objectID)
{
}
bool GameObject::collidableCheck()
{
return alive && collidable;
}
(SpaceShip.h):
#pragma once
#include "GameObject.h"
class Spaceship : public GameObject
{
private :
int lives;
int score;
int animationRow;
public :
Spaceship();
void destroy(ALLEGRO_BITMAP *image);
void init(ALLEGRO_BITMAP *image = NULL);
void update();
void render();
void moveUp();
void moveDown();
void moveLeft();
void moveRight();
void resetAnim(int pos);
int getLives(){return lives;}
int getScore() {return score;}
void looseLife() {lives--;}
void addPoint() {score++;}
void collide(int objectID);};
(SpaceShip.cpp):
#include "Spaceship.h"
Spaceship::Spaceship()
{}
void Spaceship::destroy(ALLEGRO_BITMAP *image)
{
GameObject::destroy(image);
}
void Spaceship::init(ALLEGRO_BITMAP *image)
{
GameObject::init(20, 200, 6, 6, 0, 0, 10, 12);
setID(PLAYER);
setAlive(true);
lives = 3;
score = 0;
maxFrame = 3;
curFrame = 0;
frameWidth = 46;
frameHeight = 41;
animationColumns = 3;
animationDirection = 1;
animationRow = 1;
if(image != NULL)
{
Spaceship::image = image;
}
}
void Spaceship::update()
{
GameObject::update();
if(x < 0)
x=0;
else if ( x > WIDTH)
x = WIDTH;
if(y < 0)
y = 0;
else if (y > HEIGHT)
y = HEIGHT;
}
void Spaceship::render()
{
GameObject::render();
int fx = (curFrame % animationColumns) *frameWidth;
int fy = animationRow *frameHeight;
al_draw_bitmap_region(image, fx, fy, frameWidth, frameHeight,
x - frameWidth /2, y - frameHeight /2, 0);
}
void Spaceship::moveUp()
{
animationRow = 0;
dirY = -1;
}
void Spaceship::moveDown()
{
animationRow = 2;
dirY = 1;
}
void Spaceship::moveLeft()
{
curFrame = 2;
dirX = -1;
}
void Spaceship::moveRight()
{
curFrame = 1;
dirX = 1;
}
void Spaceship::resetAnim(int pos)
{
if(pos == 1)
{
animationRow = 1;
dirY = 0;
}
else
{
curFrame = 0;
dirX = 0;
}
}
void Spaceship::collide(int objectID)
{
if(objectID == ENEMY)
lives--;
}
17
Решение
Два int
переменные определенный в заголовочном файле. Это означает, что каждый исходный файл, который включает заголовок, будет содержать их определение (включение заголовка является чисто текстовым). Конечно, приводит к множественным ошибкам определения.
У вас есть несколько вариантов, чтобы это исправить.
-
Сделать переменные
static
(static int WIDTH = 1024;
). Они будут по-прежнему существовать в каждом исходном файле, но их определения не будут видны за пределами исходного файла. -
Превратите их определения в декларации, используя
extern
(extern int WIDTH;
) и положить определение в один исходный файл:int WIDTH = 1024;
, -
Вероятно, лучший вариант: сделать переменные
const
(const int WIDTH = 1024;
). Это делает ихstatic
неявно, а также позволяет использовать их в качестве констант времени компиляции, что позволяет компилятору использовать их значение напрямую, а не выдавать код для чтения его из переменной и т. д.
48
Другие решения
Вы не можете помещать определения переменных в файлы заголовков, так как они будут частью всего исходного файла, в который вы включаете заголовок.
#pragma once
просто для защиты от нескольких включений в одном исходном файле, а не от нескольких включений в нескольких исходных файлах.
Вы могли бы объявлять переменные как extern
в заголовочном файле, а затем определять их в одном исходном файле. Или же вы можете объявить переменные как const
в заголовочном файле, и компилятор и компоновщик будут управлять им.
5
const int WIDTH = 1024;
const int HEIGHT = 800;
2
Write your question here. Hi, it is me again. I am getting this error and cannot figure out what I am doing wrong. It is in visual studios 2013 again BTW.
[#include «stdafx.h» // Precompiled header
#include «iostream» // Input and output stream
using namespace std; // Meaning you don’t have to put std:: before cout <<;.
int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();
int squareIntegers(int x) { //Function
int solution; //Declaring the variable solution, which is an integer data type.
solution = x * x; // Squaring x.
return solution; //Returns solution
}
double squareDouble(double d) {
double answer;
answer = d * d;
return answer;
}
float squareFloat(float x, float y) {
float answer1;
float answer2;
answer1 = x * x;
answer2 = y * y;
return 0;
}
int main() //Main Function
{
cout << squareIntegers(22) << endl;
cout << squareDouble(12) << endl;
cout << squareFloat(132, 150) << endl; //Function call and display with value 22 (so x = 22)
system(«pause»); // Helps with displaying the output of a program.
return 0; // Returns a value.
}
code]
Put the code you need help with here.
[/code]
Last edited on
can you use code tags please?
you need to read this:
http://www.cplusplus.com/doc/tutorial/functions/
for example, you prototype:
int squareIntegers();
but you call it like this:
squareIntegers(22)
you also do not need prototype declarations if you’re implementing them before you call them.
i.e. delete these:
|
|
Last edited on
I’m trying to but it keeps displaying like that.
besides the functions issue there is also this:
|
|
why are you doing calculations and then return zero?
edit:
you also do not need this either:
#include "stdafx.h"
Last edited on
I did it because I cannot return both answer1 and answer2 twice. What is the function issue?
please read my first post. basically these lines:
|
|
are wrong, and not even needed.
I did it because I cannot return both answer1 and answer2 twice.
You need to read that link i pasted on functions.
Okay
So, I read it but and why are
[int squareIntegers(); // Function Prototype
double squareDouble();
float squareFloat();], wrong. They are function prototypes.
Also, I get an error saying to include «stdafx.h» if I don’t include it.
Also, for squareIntegers(22), I used this in my last program, and it worked fine. I have no idea what else could be the issue.
Also, how do you use the tags. I click on <>, then this comes up: , but where in the brackets do I paste my code? I pasted in the brackets and it doesn’t work. Is there a specific location in the brackets where I should paste my code?
They are function prototypes.
Yes they are, but they don’t match your functions!
This prototype:
Tells your compiler you’re going to supply a method that takes NO parameters and returns an integer. However when you get to your code:
|
|
You’re telling the compiler about a different function. This one takes an integer and returns an integer.
This issue becomes apparent when you move your functions implementations below your main function:
|
|
errors:
(10): error C2660: ‘squareIntegers’ : function does not take 1 arguments
(11): error C2660: ‘squareDouble’ : function does not take 1 arguments
(12): error C2660: ‘squareFloat’ : function does not take 2 arguments
Because your prototypes should be:
|
|
Last edited on
Okay, thanks for that, but I still have this error: «fatal error LNK1169: one or more multiply defined symbols found.»
Does this mean in my squareFloat function, I need to make a struct, return the struct name? Will that get rid of this error?
I don’t don’t get any errors when I compile your code.
Hmmmm…. Stange. I even copy and pasted the code you had and I am still getting the error:
«fatal error LNK1169: one or more multiply defined symbols found.»
Also, I still have to add #include «stdafx.h» or else I will get an error saying I am missing that.
I’m using visual studios 2013.
I got it running!
But I have two problems.
1) It says I have to return something in the squareFloat function, but whatever I return (even 0), it will show in the output display box? What can I return that will make nothing display?
2) How do I create spaces between numbers? For example, instead of 1213, how would I make this 12 13?
Okay, I figured out the spacing part, but I still need help on the return part.
Can someone please help? This is all I need and I will be done.
what is the function meant to do? «squareFloat» implies to me that you are squaring a float? i.e. it takes in one float and returns a float.
Also, I still have to add #include «stdafx.h» or else I will get an error saying I am missing that.
what kind of project have you created?? You don’t need this at all.
Last edited on
Topic archived. No new replies allowed.