problem z includowaniem plikow

0

Witam, mam problem z includowaniem plików w C++. Problem pewnie i banalny ale przyzwyczajony od zawsze do kodzenia w javie te c++ headery sa po prostu okropne.

Mam taka sobie sytuacje:
plik a.cpp

 #include "b.cpp" {
class a {
b B;
}
}

plik b.cpp

 #include "a.cpp"
class b {
a A;
} 

I w takiej sytuacji linker mi się zapętla. A przecież to zwykła ja chce ze tak powiem zwykla relacje dwukieronkowa miedzy dwoma obiektami.

Dobra, wiec zrobmy do po bozemu tj. uzywajac header - na razie bez straznikow:

plik a.hpp

 #include "b.hpp" {
class a {
b B;
}
}

plik b.hpp

 #include "a.hpp"
class b {
a A;
} 

plik a.cpp

 #include "a.hpp" {
//metody a
}

plik b.cpp

 #include "b.hpp"
//metody a 

No ale cóz, linker dalej sie zapetla.
No wiec dodajmy straznikow, co nastepuje:

plik a.hpp

#ifndef a_HPP
#define a_HPP
 #include "b.hpp" {
class a {
b B;
}
#endif
}

plik b.hpp

#ifndef b_HPP
#define b_HPP
 #include "a.hpp"
class b {
a A;
} 
#endif

plik a.cpp

 #include "a.hpp" {
//metody a
}

plik b.cpp

 #include "b.hpp"
//metody a 

tyle, że teraz to w ogóle mi mowi , przy kompilacji dajmy na to pliku a.cpp, ze nie moze odnaleźć pliku klasy b;

Szczerze mowiac jezyka c++ nie lubie, bo jest toporny jak dla mnie :), ale jestem zmuszony cos na zajecia w nim zrobic.
Kto mi powie jak prawidlowo powinienem to zaindkludowac

0
#include "a.hpp" {
//metody a
}

co to za nadmiarowe klamry? wywal je.
Poza tym to raczej nazwy klas pisze się z dużej litery — ale to kwestia konwencji.

a.hpp

#ifndef a_HPP
#define a_HPP

#include "b.hpp"

class B;

class A {
  B b;
}

#endif

b.hpp

#ifndef b_HPP
#define b_HPP

#include "a.hpp"

class A; // ta linijka wystarczyłaby w jednym pliku. Jeśli będzie w obu — nie zaszkodzi.

class B {
  A a;
}

#endif

PS. ładniejszym od tych strażników rozwiązaniem jest #pragma once na początku pliku nagłówkowego.

0

No więc, pewnie sednem było dopisanie jedynie

 class B;

Ale nadal z tym includowaniem jest coś nie tak, jak probuje cokolwiek wywolac to mam same bledy zglaszane przez linker typu: undefinied reference to jakas_tam_funkcja

Ehh...juz nie mowiac ze c++ nie ma czegos takiego jak instanceof, ktoro musialem sam zaimplementowac oraz ze templaty w tym jezyku sa bardzo ubogie ;/

No ale nic; co jest z tymi includami ktos wie? Bo napisalem wlasnie program ale nawet nie wiem czy dobrze dziala bo nie jestem w stanie go uruchomic

0

To w klasie daj tylko deklaracje funkcji (typu: void Func(int);), a definicje(void Func(int a) { return Zmienna[a];}) w odpowiadających im plikach cpp.

0

to mam tak jak piszesz właśnie, i mam wrażenie że includując jakiś plik .hpp po prostu linker nie widzi pliku .cpp ktory oczywiscie includuje .hpp

0
// a.cpp
#include "a.hpp"
#include "b.hpp"
int A::Func(int a)
{
    B Obj;
    return Obj.Func(a);
}
int B::Func(int a)
{
    return a*a/a*a;
}
 

Nie ma innej rady, niż includować przed a.cpp b.hpp.

1
class a {
b B;
}

class b {
a A;
} 

Pomyśl, co to ma właściwie oznaczać? Chcesz zrobić klasę a, która zawiera klasę b, która z kolei znowu zawiera klasę a i tak w kółko. Któraś z tych klas (albo obie) muszą zawierać wskaźnik na drugą.

0

No właśnie... weź to na wskaźniki pozamieniaj, bo to nie java... tutaj jak piszesz B zmienna, to masz obiekt, a nie referencję do obiektu, która może wskazuje na coś, a może nie. forward declaration padło. Więc używaj, najlepiej hurtem, w obu plikach na początku (a.hpp, b.hpp)

class A;
class B;
class ....

class A {
  B* b;
};

nie include'uj plików .cpp na Boga...

masz dwa pliki a.cpp i b.cpp - include'uj w nich hurtem

#include "a.hpp"
#include "b.hpp"

skoro pisałeś/piszesz w Javie, to używaj konwencji nazewniczej Javy. Bo dobra jest. Teraz to jest horror.

int A::Func(int a)
{
    B Obj;
    return Obj.Func(a);
}

Mam nadzieję, że jesteś świadom, że w tej funkcji nie odwołujesz się do składowej klasy, tylko na chama tworzysz obiekt B, po to tylko, żeby za chwilę go wywalić. Po co więc w klasie A umieszczałeś składową typu B, skoro i tak w funkcjach tymczasowe tworzysz ?

Skoro taki Javowy jesteś, to użyj chociaż jeden raz etykiety private/public - w Javie przy każdej składowej i funkcji trzeba... może Ty jakoś sobie to rekompensujesz, i w C++ nie wstawiasz wcale ?

C++ ma funkcjonalność oferowaną przez instanceof, i to dwóch różnych rodzajów, albo opartą o wyjątki, albo o zwykłe true/false.

Object* value = ...

// ... if'em
if( dynamic_cast<MyOwnType*>(value) ) 

// ... wyjątkami
try { 
    MyOwnType& mtvalue = dynamic_cast<MyOwnType&>(*value); 
} catch(...) {
    // ...
}

Na czym polega "ograniczenie" szablonów, ... od czego są uboższe? Od generics'ów? W których nawet nie możesz jawnie utworzyć typu będącego parametrem? Od generics'ów, które na poziomie skompilowanego kodu są totalną sieczką pracującą na typie Object i dokonującą 100 rzutowań na minutę? Nawet twórcy Javy mówią wprost - genericsy dodano, bo "idea wspólnego korzenia" nie okazała się taka genialna, jak się spodziewano. A jak dodano, to tak, żeby kompatybilność była... i wyszedł potwór którego zdaje się będą ulepszać dopiero. Zresztą nie wiem czy będą. Nie patrzyłem ostatnio. Z rok temu próbowałem z tym walczyć. Teraz po prostu używam jak Bóg przykazał. Bez cudów.

Pytanie, w jaki więc sposób Ty próbujesz szablonów używać w C++ ? Bo innymi się rządzą zasadami niż w Javie. A potężniejsze są znacznie.

Ogółem Panie - jeśli nie znasz języka, to nie kłapaj dziobem, tylko na spokojnie do niego przysiądź. Jak się Javy uczyłem to też na początku kłapałem, bo ideowo nie cierpię języków latających na VM. Ale dosłownie po 2 dniach mi przeszło. Nie dlatego, że Java jest supersiejsza, tylko dlatego, że zaakceptowałem, że w innym języku są inne idiomy i konwencje.

0

mam wrażenie że includując jakiś plik .hpp po prostu linker nie widzi pliku .cpp ktory oczywiscie includuje .hpp

Oczywiście że nie widzi. Musisz go skompilować a potem zlinkować to wszystko w plik wykonywalny. Jeśli robisz to w jakimś IDE to zapewne wystarczy stworzyć z tego projekt, jeśli kompilujesz ręcznie to musisz to sam zlinkować.

0

Wypowiem się jako początkujący w C++. I właściwie jest to podobne do tego, co napisał @Ranides.

Po wielu, wielu dniach i próbach walki z includowaniem zacząłem stosować proste rozwiązanie składające się z 3 punktów:

  1. uzycie forward declaration
  2. składniki klas w plikach .h używają praktycznie zawsze wskaźników do innych klas
  3. wyjątek od reguły 2 stanowią jakieś podstawowe klasy typu cPoint, które nie includują innych klas

Do tej pory zawsze się sprawdza.

pzdr
squash

1 użytkowników online, w tym zalogowanych: 0, gości: 1