Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

C++ - Dzielenie plików źródłowych

daniel93 07 Paź 2012 23:51 2604 40
  • #1 07 Paź 2012 23:51
    daniel93
    Poziom 29  

    Napisałem program do transmisji danych przez RS232, który działa gdy jest w jednym pliku. Schody zaczęły się gdy chciałem go podzielić:

    main.cpp:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    UART.cpp:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    UART.hpp:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Kompilator wywala takie błędy:
    Kod: text
    Zaloguj się, aby zobaczyć kod


    Czego zupełnie nie rozumiem, bo wywala mi zduplikowane definicję, a przeciez są zdefiniowane tylko w UART.hpp :|

    0 29
  • #2 08 Paź 2012 14:12
    szefkozak
    Poziom 11  

    Nie możesz w pliku *.hpp definiować zmiennych, poza zmiennymi const.

    0
  • #3 08 Paź 2012 20:59
    daniel93
    Poziom 29  

    Tylko gdzie? Przeniosłem je na początek głównego pliku i jest jeszcze więcej błędów:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    [EDIT]
    Jak wrzuciłem je do pliku UART.cpp to problem jest ze zmiennymi w pliku main.cpp:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #4 08 Paź 2012 21:01
    gaskoin
    Poziom 38  

    Mają być zadeklarowane w cpp. Z resztą jezyk, w którym tworzysz jest bardzo daleki od C++.

    0
  • #5 08 Paź 2012 21:08
    daniel93
    Poziom 29  

    Ale jak jakaś zmienna jest w dwóch plikach cpp to ma byc zadeklarowana w obu?

    Dlaczego daleki?

    0
  • #6 08 Paź 2012 21:13
    stanleysts
    Poziom 27  

    Poprzez dodanie słowa kluczowego extern, gaskoin ma zapewne na myśli to, że to powinno być w jakąś klasę opakowane z wewnętrznymi metodami i odpowiednimi polami.

    0
  • #7 08 Paź 2012 21:14
    gaskoin
    Poziom 38  

    Bo C++ jest językiem obiektowym a nie funkcyjnym. Powinieneś to jakoś opakować rozsądnie w klasy. To co napisałeś to takie C rozszerzone o biblioteki C++.

    Rozwiązaniem typu walnięcie młotem jest deklaracja tych zmiennych w *.cpp a w hpp dodanie deklaracji tych zmiennych poprzedzając je słowem kluczowym extern. Walnięcie młotem dlatego, ponieważ współdzieląc zmienne pomiędzy kilkoma plikami (Ty masz 3 więc przeżyjesz :) ) zaczyna się robić bałagan. Wyobraź sobie co się będzie działo jak będziesz potrzebował wysyłać coś przez RS z 10 różnych plików.

    W C robi się to tak, że tworzy się odpowiednie funkcje do ustawiania i zwracania zmiennych z danego pliku. W C++ jest w zasadzie podobnie. Jakbyś opakował to w klasy, to Twój kod w mainie wyglądałby tak:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    I nie potrzebowałbyś wcale tych zmiennych mieć jako globalne.

    0
  • #8 14 Paź 2012 16:52
    daniel93
    Poziom 29  

    Pomińmy na razie opakowanie tego w klasy.

    Ale jak w ogóle współdzielić zmienną w kilku plikach?

    Próbowałem zrobić tak jak pisał gaskoin. Zdefiniowałem zmienne w UART.cpp. A w UART.hpp dodałem definicje tych 2 zmiennych które chce współdzielić ze słówkiem extern i kompilator wywala blędy które nie mają zwiazku ze zmianą jaką wprowadziłem:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    0
  • #9 14 Paź 2012 16:54
    stanleysts
    Poziom 27  

    Pokaż kod jak możesz.

    0
  • #10 14 Paź 2012 16:57
    daniel93
    Poziom 29  

    main.cpp:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    UART.cpp
    Kod: cpp
    Zaloguj się, aby zobaczyć kod

    UART.hpp
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Zanim dopisałem te 2 linijki były tylko 2 błędy, które wcześniej wklejałem( te o bufn i bufn_i)

    0
  • #11 14 Paź 2012 17:02
    stanleysts
    Poziom 27  

    W pliku nagłówkowym nie możesz mieć tych zmiennych co o nie się pluje, zrób to w pliku .cpp a w .hpp tylko deklaracje z extern. Tak to miałbyś 2 kopie tej samej zmiennej.

    0
  • #12 14 Paź 2012 17:29
    daniel93
    Poziom 29  

    Ale o które dokładnie zmienne Ci chodzi?

    Bo on sie pluje o CommTimmeouts itp., a to przeciez nawet nie jest zmienna

    0
  • #13 14 Paź 2012 17:30
    stanleysts
    Poziom 27  

    A to w takim razie to co to jest? Przecież to są obiekty albo zmienne.

    0
  • #14 14 Paź 2012 17:58
    daniel93
    Poziom 29  

    Mógłbyś mi pokazać kolego który fragment hpp powinien być tez w cpp, a w hpp z dodatkiem extern?

    0
  • Pomocny post
    #15 14 Paź 2012 18:06
    stanleysts
    Poziom 27  

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Jeśli np. z niektórych zmiennych korzystasz tylko w module usart a nie w main to możesz je zrobić jako global static (chyba te zmienne const się do tego nadają) i wtedy nie trzeba ich też extern robić bo main z nich nie korzysta

    0
  • Pomocny post
    #16 14 Paź 2012 18:39
    gaskoin
    Poziom 38  

    stanleysts napisał:
    Jeśli np. z niektórych zmiennych korzystasz tylko w module usart a nie w main to możesz je zrobić jako global static (chyba te zmienne const się do tego nadają) i wtedy nie trzeba ich też extern robić bo main z nich nie korzysta


    const musi być znany podczas kompilacji a nie jest. Przerzuć te zmienne do pliku cpp i będzie ok.

    Ja może wyjaśnię w czym problem. Masz sobie plik hpp, w którym deklarujesz zmienne (nigdy nie wolno tego robić):

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Masz też dwa pliki cpp, w których includujesz sobie ten plik hpp:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Co widzi kompilator (a w zasadzie linker)?
    Kompilator w uproszczeniu widzi coś takiego:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Jak w jednym pliku zadeklarujesz takie same zmienne, to otrzymasz taki sam błąd jak Ci wyskakuje. Może nie jest to jasne i oczywiste, ale zmienne zadeklarowane jako globalne, są dostępne nie tylko w obrębie całego pliku, ale całego programu. O fakcie, że zmienne zostały zadeklarowane gdzieś indziej informuje się linker poprzez dodanie słowa kluczowego extern (nie alokuje to pamięci dla zmiennych, jest to jedynie info dla linkera, że zmienna jest w innym pliku). Deklarując zmienną w w pliku nagłówkowym, deklarujesz ją w każdym pliku, w którym ten nagłówek includujesz. Stąd te błędy.

    0
  • #17 14 Paź 2012 20:53
    daniel93
    Poziom 29  

    Ok udało się :)

    A jak zrobić ten global static? Robi sie go w cpp czy hpp?

    Dodano po 24 [minuty]:

    Dopiero teraz zauważyłem posta gaskoin - dzięki, teraz rozumiem o co w tym chodzi. Zastanawiam sie czy nie lepiej było by zrobić oddzielny plik nagłówkowy dla każdego pliku + jeden z globalnymi zmiennymi?

    Dodano po 17 [minuty]:

    Mam jeszcze pytanie, bo klasy pozwoliłyby mi robić tak:

    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Jednak mi zalezy, żeby wysyłać wartości liczbowe czyli po prostu pojedyncze bajty. Jak zrobić funkcję żebym mógł robić tak?:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Gdzie każda liczba to osobny bajt, ale problem w tym, żeby ilość bajtów mogła być różna. Tzn w tym przykladzie wysyłam 4 bajty, ale chciałbym w taki sposób wysyłać też 3 albo 10, a funkcja ta pakowała by to do tablicy i informowała ile jest bajtów do wysłania.

    Dodano po 41 [minuty]:

    Przyszło mi do głowy tylko coś takiego:
    Kod: cpp
    Zaloguj się, aby zobaczyć kod


    Krótsze dane można kończyc zerami, które funkcja zinterpretuje jako koniec

    0
  • #18 14 Paź 2012 21:07
    gaskoin
    Poziom 38  

    Lepszym pomysłem jest użycie jako parametrów wskaźnika na tablicę z danymi oraz jej rozmiar.

    0
  • #19 14 Paź 2012 21:27
    daniel93
    Poziom 29  

    Wiem, że można tak zrobić, ale właśnie chodzi mi o prostu sposób na wypełniamie tej tablicy

    Będe używać tego wielokrotnie, dlatego chciałem to uprosić

    0
  • #20 14 Paź 2012 21:40
    stanleysts
    Poziom 27  

    Parametr wskaźnik na tablicę i jej rozmiar to jest prosty wygodny i porzadny sposób.

    0
  • #21 14 Paź 2012 21:42
    daniel93
    Poziom 29  

    Tak, ale nie pozwoli mi to na wpisywanie wartości po przecinku i musze z góry wiedzieć ile tych wartości jest

    0
  • #22 14 Paź 2012 22:18
    stanleysts
    Poziom 27  

    A po co masz po przecinku wpisywać? wpisujesz do tablicy, inrementujesz licznik za każdym razem i potem wskaźnik na tablicę i licznik jako parametry funkcji. To jest imho
    dużo lepsze rozwiązanie.

    0
  • #23 14 Paź 2012 22:32
    daniel93
    Poziom 29  

    Bo to będzie ciąg komend wysyłanych do różnych urządzeń:
    134 - adres urządzenia
    12,34,78,21 - komendy
    145 - CRC8
    255 - sygnał końca ramki

    Takie coś dużo wygodniej było by napisać w postaci:
    134,12,34,78,21,145,255 niż jak miałbym wypisywać jeden pod drugim

    0
  • #24 14 Paź 2012 23:09
    stanleysts
    Poziom 27  

    No i ja tak dalej nie wiem, dlaczego nie możesz użyć metody ze wskaźnikiem i rozmiarem...

    0
  • #25 14 Paź 2012 23:14
    gaskoin
    Poziom 38  

    Jest na to wygodny sposób, ale programować obiektowo Ci się nie chce więc nie pomogę :)

    0
  • #26 14 Paź 2012 23:17
    stanleysts
    Poziom 27  

    Chodzi Ci gaskoin o skorzystanie z szablonów, przeładowania czy może jszcze czegoś innego?

    0
  • #27 14 Paź 2012 23:21
    daniel93
    Poziom 29  

    stanleysts,
    Ale ze wskaźnikiem wyglądało by to tak:
    Write(char *buff, dlugosc), a wczesniej by trzeba było wpisywać:
    buff[0] = 134
    buff[1] = 12
    itd

    gaskoin, chce mi się tylko jeszcze nie umiem :p

    0
  • #28 15 Paź 2012 00:06
    stanleysts
    Poziom 27  

    No ale podawać bezsensownie niepotrzebne parametry albo wysyłać resztę danych jako zera to lepszy pomysł? Poza tym zrobiłbyś to jeśli nie na klasach to na jakichś strukturach, żeby ładniej wyglądało i było czytelne.

    0
  • #29 15 Paź 2012 00:17
    daniel93
    Poziom 29  

    stanleysts: własnie ze funkcja mogła by wykryć zera i zakończyć transmisje - masz lepszy pomysł żebym mógł polecenie napisać w jednej linijce a nie w 10?

    0
  • #30 15 Paź 2012 00:21
    stanleysts
    Poziom 27  

    Przeładowanie funkcji?
    A jak będziesz chciał wysłać akurat zero a funkcja Ci obcina zera to co?

    0