» »

[C++]Uporaba strukture v drugi .cpp datoteki

[C++]Uporaba strukture v drugi .cpp datoteki

gtu ::

Pozdravljeni,
imam izjemne težave z uporabo struct-a v dveh cpp datotekah.
Deklariran in definran je v datoteki "funkcije.h":
struct data{
	int integer = 0;
	Mat & picture = Mat(1280, 960, CV_8UC3);
}podatki;

Ustvari se tudi objekt "podatki".
strukturo uporabim v eni funkciji v datoteki "funkcije.cpp":
void funkcija(data a){
	doSomething(a.picture);
}

ki jo kličem v "main.cpp":
funkcija(podatki)


kakšna ideja?
Hvala

Compiler spusti čez, ustavi se pri linkerju, in sicer:
Error	17	error LNK2005: "struct data podatki" (?podatki@@3Udata@@A) already defined in funkcije.obj	
Error	18	error LNK1169: one or more multiply defined symbols found	

mn ::

Dodaj #ifdef sekcijo v header file:

#ifdef HEADER_FILE_NAME
#define HEADER_FILE_NAME
struct data{
    int integer = 0;
    Mat & picture = Mat(1280, 960, CV_8UC3);
}podatki;
#endif


Kar se ti sedaj zgodi je, da linker vidi struct data dvakrat in se seveda pritoži. Enako kot da bi ga dvakrat napisal.

gtu ::

tudi po tem ko dodam ifdef se pritoži.
Zelo čudno

galu ::

#ifndef
mora biti :)
Tako to gre.

mn ::

galu je izjavil:

#ifndef
mora biti :)


Seveda, #ifndef. Ampak zanimivo, da dobi enako napako. Moral bi dobiti "undeclared symbol data" ali kaj podobnega.

gtu ::

Je mogoče težava v tem, da se kreira objekt že takoj pri definiciji structa in potem ta isti objekt uporabljam v drugem cppju?
Bi moral morda naredit še en poseben header samo za strukturo, samo ne vem kaj bi s tem izboljšal?

redo ::

gtu je izjavil:

Je mogoče težava v tem, da se kreira objekt že takoj pri definiciji structa in potem ta isti objekt uporabljam v drugem cppju?

Da. Težava je v tem, da je globalna spremenljivka podatki definirana v dveh objektnih datotekah, ki jih linker ne zna povezati skupaj. Ena rešitev je, da v header datoteki uporabiš besedo extern, s čemer prevajalniku eksplicitno poveš, da je spremenljivka samo deklarirana, definirana pa je nekje drugje. Nato samo v eni od cpp datotek definiraš spremenljivko podatki.

Npr.: v headerju
struct data {};
extern struct data podatki;

v eni cpp datoteki:
struct data podatki;

Druga možnost je, da v header datoteki definiraš podatki kot statično spremenljivko

struct data {};
static struct data podatki;

V tem primeru bo spremenljivka podatki lokalna vsaki prevajani enoti (datoteki).

gtu ::

redo je izjavil:


Npr.: v headerju
struct data {};
extern struct data podatki;

v eni cpp datoteki:
struct data podatki;


Evo končno sem imel čas sprobati in zadeva deluje, zato sem uporabil le prvo možnost ki si jo podal. HVALA!
Vseeno mi pa še ni čisto jasno, zakaj sta bila prej definirana dva objekta? Se to zgodi zaradi #include headerja v katerem je bil struct?
Ali moram, če želim isti struct uporabiti še v tretji cpp datoteki, v njen header dati definicijo structa, ali samo includam prejšnji header? Kako je v tem primeru z objektom podatki? Ali je dostopen funkcija tretje cpp datoteke?
(Potihem razmišljam, da je dovolj samo include prejšnjega headerja, kjer je že definicija structa)

Rad bi si razjasnil to, da ne bom samo uporabljal nečesa brez da bi vedel kako deluje :)

Zgodovina sprememb…

  • spremenil: gtu ()

Senitel ::

To kar ti delaš je zlo khm...
Ti imaš struct data in imaš instanco podatki. Vsakič, ko narediš include tega headerja compilerju tudi poveš, da hočeš naredit novo globalno instanco spremenljivke z imenom "podatki", ki že obstaja.
Skratka v glavi si moraš ločit, da struct in instanca nisto eno in isto.
Plus tvoja inicializacija memberjev v structu/class-u ni ravno standardna (kater compiler ti to pusti?).

gtu ::

Senitel je izjavil:

To kar ti delaš je zlo khm...
Ti imaš struct data in imaš instanco podatki. Vsakič, ko narediš include tega headerja compilerju tudi poveš, da hočeš naredit novo globalno instanco spremenljivke z imenom "podatki", ki že obstaja.
Skratka v glavi si moraš ločit, da struct in instanca nisto eno in isto.

To sem rešil kot mi je svetoval "redo". Struct sem na začetku naredil samo v prvem cppju in je tam ta instanca povsem pravilno delovala, zato je tudi v prenosu v header to tamo ostalo. Saj to ločim, da struct je le "oblika", ki jo ima instanca "podatki" (in morebitne druge). Le nisem vedel kako se obnaša pri vključevanju drugam.

Senitel je izjavil:

Plus tvoja inicializacija memberjev v structu/class-u ni ravno standardna (kater compiler ti to pusti?).

To je pa posledica tega, da me compiler ni pustil čez, če memberji niso bili inicializirani. Vem da so ponavadi samo imena, ampak meni ni delovalo, zato je tam tako kot je. Katera je prava pot?

Hvala, lp

Zgodovina sprememb…

  • spremenil: gtu ()

Senitel ::

Vse kar se vključuje (include) drugam se interpretira še enkrat. Zato tudi #ifndef/#define mehanizem omenjen zgoraj.

Compiler se ti je pritožil ker v strukturi shranjuješ referenco nekam (member picture) in ta mora vedno kazat nekam. Pravilno to narediš tako, da te stvari nastaviš v konstruktorju.

gtu ::

Senitel je izjavil:

Vse kar se vključuje (include) drugam se interpretira še enkrat. Zato tudi #ifndef/#define mehanizem omenjen zgoraj.

Compiler se ti je pritožil ker v strukturi shranjuješ referenco nekam (member picture) in ta mora vedno kazat nekam. Pravilno to narediš tako, da te stvari nastaviš v konstruktorju.

Ahaaaa, hvala.
Sicer ta #ifndef je bil že prej vključeno, samo nisem kopiral v prvi post, ker se mi ni zdelo pomembno (zdaj se mi :) ).

Sepravi povsem pravilna verzija bi bila:

Header:
#ifndef _struktura_
#define _struktura_
struct data{
    int integer;
    Mat & picture;
  };
extern struct podatki;
#endif // !_struktura_


Main cpp:
struct podatki(stevilka, objektTipaMat);



Je to sedaj pravilno in po standardih, da ni več:
zlo khm...

:)

Zgodovina sprememb…

  • spremenil: gtu ()

redo ::

gtu je izjavil:


Vseeno mi pa še ni čisto jasno, zakaj sta bila prej definirana dva objekta? Se to zgodi zaradi #include headerja v katerem je bil struct?

Da. V includanem headerju je bila definicija globalne spremenljivke/instance podatki. Include ni nič drugega, kot "skopiraj vsebino includane datoteke sem." Nekateri programski paketi to precej prostodušno in IMHO nemarno izrabljajo. Omenjeni #ifndef/#define konstrukt pa ščiti proti temu, da bi nek header file includal dvakrat (ali pa npr. da bi ciklično includal dva headerja). Pri tvojem problemu nima nekega pomena, je pa dobra praksa pri pisanju header datotek.

gtu je izjavil:


Ali moram, če želim isti struct uporabiti še v tretji cpp datoteki, v njen header dati definicijo structa, ali samo includam prejšnji header?

Samo includaš header. Ne smeš podati definicije. Sicer boš naletel na isti problem.

gtu je izjavil:


Kako je v tem primeru z objektom podatki? Ali je dostopen funkcija tretje cpp datoteke?
(Potihem razmišljam, da je dovolj samo include prejšnjega headerja, kjer je že definicija structa)

Če si uporabil extern rešitev, potem je dostopen tudi funkcijam v tretjem cpp. Če si uporabil static, potem ne. Čeprav kolikor sem videl, ti itak podajaš "podatki" kot argument funkciji, tako da v primeru, ki si ga zapisal nima pomena ustvarjati globalne spremenljivke/instance.

Na ostale napake te bo že kdo drug opozoril. Jaz sem samo odgovoril za omenjeno napako, ker sem videl, da so se ostali komentatorji malo lovili.

gtu ::

Dobro dobro, hvala, res nisem več vedel kaj naj poizkusim. Sedaj je TA težava rešena :) (ko odpraviš eno, se jih pojavi še 10).

mallard ::

Senitel je izjavil:

To kar ti delaš je zlo khm...
Plus tvoja inicializacija memberjev v structu/class-u ni ravno standardna (kater compiler ti to pusti?).


In-class inicializacija je standardna od C++11 naprej. Tako da...

struct data {
    int i = 1;
};

... je v redu in je enako kot:
struct data {
    int i;
    data() : i(1) {}
};


Inicializacija reference pa ni v redu, ker je ne moreš inicializirat z začasnim objektom (ni const).

Zgodovina sprememb…

  • spremenilo: mallard ()


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[C] Seznam s poljem

Oddelek: Programiranje
232450 (1930) aceton
»

C++(bin file) vprašanje

Oddelek: Programiranje
121482 (1360) technolog
»

Qt Designer -> KDevelop C++ Error

Oddelek: Programiranje
352111 (1641) 'FireSTORM'
»

[C++] prevajalnik hoce konstruktor za strukturo

Oddelek: Programiranje
182587 (2291) Tr0n
»

problem pri linkanju c++

Oddelek: Programiranje
7984 (935) atasmrk

Več podobnih tem