Forum » Programiranje » [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":
Ustvari se tudi objekt "podatki".
strukturo uporabim v eni funkciji v datoteki "funkcije.cpp":
ki jo kličem v "main.cpp":
kakšna ideja?
Hvala
Compiler spusti čez, ustavi se pri linkerju, in sicer:
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:
Kar se ti sedaj zgodi je, da linker vidi struct data dvakrat in se seveda pritoži. Enako kot da bi ga dvakrat napisal.
#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.
mn ::
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?
Bi moral morda naredit še en poseben header samo za strukturo, samo ne vem kaj bi s tem izboljšal?
redo ::
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 ::
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?).
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 ::
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.
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.
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 ::
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 ::
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.
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.
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 ::
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 ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | [C] Seznam s poljemOddelek: Programiranje | 2470 (1950) | aceton |
» | C++(bin file) vprašanjeOddelek: Programiranje | 1508 (1386) | technolog |
» | Qt Designer -> KDevelop C++ ErrorOddelek: Programiranje | 2127 (1657) | 'FireSTORM' |
» | [C++] prevajalnik hoce konstruktor za strukturoOddelek: Programiranje | 2641 (2345) | Tr0n |
» | problem pri linkanju c++Oddelek: Programiranje | 993 (944) | atasmrk |