Korzystanie z obiektu klasy A w klasie B i odwrotnie.

0

Witam,
mam problem z klasami w C++. Chce korzystac z metod klasy B w klasie A i odwrotnie.
Problem mam już z dołączaniem plików nagłówkowych.

//**************** header klasy Containter
#pragma once
#include "Containter.h"
class Circle
{
       int circleValue;
public:
     
	Containter container; 
	Circle();
	~Circle();
    void SetCricleValue(int value)

};




//**************** header klasy Circle
#pragma once
//#include "Circle.h" // bez dołączania klasy Circle program się kompiluje ale gdy usunę komentarz program nie się nie kompiluje.
class Containter
{
        int containterValue;
public:
	//Circle circle;
	Containter();
	~Containter();
   void SetContainterValue(int value);
};

W jaki sposób mogę utworzyć obiekt klasy Circle w klasie Containter bez dołączenia "Circle.h"? Gdy tego nie zrobię wewnątrz klasy Container nie mam dostępu do Cricle.
Nie chcę używać tutaj dziedziczenia bo te klasy mają inne zadania.
Potrzebuje tylko aktualizować stan obiektu przez wywoływanie metod - w klasie Circle musze wywołać UpdateContainterValue() z klasy Containter, a w klasie Containter UpdateCircleValue().

Z góry dziękuję za pomoc.
Pozdrawiam

1

Problem XY? Skąd kompilator ma wiedzieć o klasie Circle, jeśli mu nie Dołączysz tej klasy?

0
lion137 napisał(a):

Problem XY? Skąd kompilator ma wiedzieć o klasie Circle, jeśli mu nie Dołączysz tej klasy?

No własnie w tym problem, że nie wiem. Tak jak w poście wyżej:

#pragma once
//#include "Circle.h" // bez dołączania klasy Circle program się kompiluje ale gdy usunę komentarz program nie się nie kompiluje.
class Containter

Jak dołączam mu tą klasę to nie działa. Mogę tylko dołączyć do "Circle" klasę "Containter", a jak chcę jeszcze dołączyć w do "Containter" klasę "Circle" to nie działa. Myślałem, że "pragma once" rozwiąże problem ale nie pomogło.

4

Chcesz użyć forward deklaracji. Powątpiewam, czy to rozwiązanie rzeczywistego problemu, ale jest to rozwiązanie problemu, o który pytałeś.

// foo.h

struct bar;
struct foo
{
    void x(bar const&);
};

// bar.h

struct foo;
struct bar
{
    void x(foo const&);
};
3

Pozwól, że zapytam o jedną rzecz - DLACZEGO chcesz, żeby Circle zawierało w sobie Container ?

0

Dzieki wszystkim za odpowiedzi, bede dzisiaj kombinowal. Z tego co widze nie ma prostego rozwiazania. Myslalem, ze moze jest jakis trick z "#include", ktory szybko rozwiaze problem.
Mam jeszcze jeden pomysl stworzenia trzeciej klasy, ktora by aktualizowala wartosci klas Cricle i Contatiner. Wrzuce rozwiazanie jak sie uda.

Pomijajac problem aktualizowania wartosci i tworzenia obiektow w klasach. Moglby mi ktos wytlumaczyc dlaczego dolaczenie plikow naglowkowych w obu klasach powoduje blad?
tzn.

plik Circle.h

#include "Container.h"
Class Circle {
}

plik Containter.h

#include "Circle.h"   // dodanie tego powoduje blad
Class Containter {
}
3

No bo masz cykliczną zależność, @kq Ci napisał jak to obejść. Include = weź zawartość pliku i ją wklej w miejsce dyrektywy. No to do Container.h kleisz Circle.h, które zawiera Container.h, które zawiera Circle.h i tak ad mortem defecatum. Zrobiłeś sobie przedzidzie śródzidzia zadzidzia przedzidzia śródzidzia zadzidzia przedzidzia (...) dzidy bojowej.

2

Raczej nie najlepsze rozwiązanie, ale powinno działać.

//Circle.hh

class Container;

class Circle{
    Container *container;
}

//Circle.cc
#include "Container.hh"

//Container.hh

class Circle;

class Container{
    Circle *circle;
}

//Container.cc
#include "Circle.hh"

0

Dziekuje wszystkim za pomoc. Udalo mi sie rozwiazac problem korzystajac z forward declaration. Wyglada to troche skomplikowanie i niezbyt czytelnie.
Czy w komercyjnym kodzie stosujecie forward declaration czy powinno sie tego unikac?

1

Nie wiem jak w komercyjnym kodzie ale troche w c++ programowalem i dla mnie to tez nieczytelne.
Ale dziala i nawet jest stosowane.
Chyba mozna to podciagnac pod "rozwiazanie idiomatyczne".

3

Jak najbardziej jest to rozwiązanie idiomatyczne. Przede wszystkim, pozwala uniknąć zaciągania kolejnych include'ów i znacznie przyspiesza kompilację/rekompilację. (Jeśli zmieniło się foo.h, to a includuje go bar.h to wszystko includujące bar.h też zostanie przekompilowane). Ponadto, w mojej opinii zwiększa czytelność, ponieważ poprawnie stosowane pozwala od razu stwierdzić w jaki sposób dany typ jest wykorzystywany i jak głęboka jest od niego zależność.

Ale i tak nie mogę doczekać się modułów.

0

Witam ponownie. Pierwotny problem rozwiazalem ale zeby nie tworzyc nowego tematu dodam tutaj pytanie. Czy dobrze tworze obiekt klasy Container? Jezeli tak to gdzie zwolnic pamiec? w destruktorze?


class Circle
{
     Containter* container;
public:
    Circle();
};

Circle::Circle()
{
	containter = new Containter();
}
1

Najlepiej to by było użyć unique_ptr albo shared_ptr i pozwolić ich destruktorom to zrobić. O ile musisz to robić na stercie, bo może pole typu Container zamiast Container* styka.

0
alagner napisał(a):

Najlepiej to by było użyć unique_ptr albo shared_ptr i pozwolić ich destruktorom to zrobić. O ile musisz to robić na stercie, bo może pole typu Container zamiast Container* styka.

Pole nie wystarczy niestety bo przy tworzeniu obiektu musze do konstruktora przekazac parametr. Poczytam o smart pointerach :)

1

Użyj według poniższego schematu, gdzie p1,p2,p3 są parametrami przekazywanymi do konstruktora obiektu Container

class Circle
{
     unique_ptr<Containter> container {nullptr};
public:
    Circle();
};

Circle::Circle()
{
    containter = make_unique<Containter>( p1 , p2  , p3 );
}
0
TomaszLiMoon napisał(a):

Użyj według poniższego schematu, gdzie p1,p2,p3 są parametrami przekazywanymi do konstruktora obiektu Container

Powinienem uzyc unique_ptr czy shared_ptr? Przeczytalem, krotki wstep do smart pointerow i wyglada jakby shared_ptr bardziej pasowal. Dobrze mysle?

class Circle
{
    std::shared_ptr<Container> container;
public:
    Circle();
};

Circle::Circle()
{
    container= std::shared_ptr<Container>(new Container());
}
2

Jeżeli obiekt container nie będzie udostępniany na zewnątrz klasy Circle to wystarczy unique_ptr. Jeżeli planujesz użycie większej ilości wskaźników przypisanych do tego obiektu - użyj shared_ptr.
Do tworzenia wskaźnika zalecane jest używanie funkcji szablonowych make_unique<> , make_shared<>.

class Circle
{
     shared_ptr<Containter> container {nullptr};
public:
    Circle();
};

Circle::Circle()
{
    containter = make_shared<Containter>( p1 , p2  , p3 );
}

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