Skocz do zawartości
Zaloguj się, aby obserwować  
DevPort

klasy

Polecane posty

Dobra miałem pewien problem ze strony kompilatora C++

 

struktura klas:

class A
{
public:
  A(){ b = new B; c = new C;}
  B* b;
  C* c;
};

Teraz magiczne zdanie:

Chciałem dostać się z klasy B do klasy C.

 

Główkowałem cały dzień jak to zrobić, kombinowałem z interfejsami (w delphi/fpc to nie problem) ale poległem.

Przyszedł mi jednak pewien pomysł na rozwiązanie problemu.

Przekazanie instancji klasy A do pozostałych klas czyli B i C przez konstruktor.

 

Czyli tu mamy błędny kod:

B::B(A* base)
{
}

C::C(A* base)
{
}

Ponieważ musimy do plików nagłówkowych klas B i C dołączyć plik nagłówkowy klasy A który zawiera w sobie dołączone pliki nagłówkowe klas B i C.

 

Więc jak?

W ukochanym Object Pascalu mamy wskaźnik niejawny : Pointer; 4 bajtowy.

W C++ odpowiednikiem jest "void* zmienna;"

 

Ta, wielu więc napisze: to proste więc zamieńmy w konstruktorach A* na void* i po sprawie...

Ne ne ne

 

Kompilatorek wywali błąd konwersji :)

I tu szczena mi opadła :(

 

Ale coś musi być, aby to działało i jest:

static_cast

 

więc tak piszę w/g plików:

"a.h"

#include "B.h"
#include "C.h"

class A
{
public:
 A();
 B* b;
 C* c;
}

 

"a.cpp"

#include "A.h"
A::A()
{
 b = new B(this);
 c = new C(this);
}

 

Teraz pliki pozostałych klas:

"b.h"


class B
{
public:
 B( void* base);

}

 

"b.cpp"

#include "B.h"
#include "A.h"

A* mA;
B::B(void* base)
{
 mA = static_cast<A*>(base);
}

 

 

"c.h"


class C
{
public:
 C( void* base);
 void test();
}

 

"c.cpp"

#include "C.h"
#include "A.h"
#include <iostream>

A* mA;
C::C(void* base)
{
 mA = static_cast<A*>(base);

}

void C::test()
{
std::cout << "Witaj świecie \n";
}

 

Teraz w metodach klasy B możemy używać zapisu:

 mA->c->test();

 

 

Komuś może się przydać taka konstrukcja kodu.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Ojojoj... W C++ void * należy używac w ostateczności (czyli uzycie takiego to z prawdopodobieństwem 1 użycie błędne).

Dodatkowo zmienne globalne... brrr....

 

Podpowiedć, np plik c.h może wyglądac tak:

 

class A;
class C
{
public:
 C( A* base);
 void test();
}

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Testowałeś to ?

Możesz podać działający przykład?

Albo nie umiem i nie działa, albo gdzieś popełniłeś błąd.

 

Cel to dostęp do klasy, która nas (klasę) stworzyła.

Czyli w plikach nagłówkowych klas: B i C nie mogę dołączać pliku nagłówkowego klasy A, ponieważ jej plik nagłówkowy dołącza pliki nagłówkowe klas B i C.

 

Czyli w tych plikach nie dam rady stworzyć zmiennej wskaźnikowej na klasę A.

A chcę wykorzystać właśnie funkcje tej klasy.

Więc potrzebna mi jej instancja klasy A wewnątrz klas B i C.

 

Odnośnie tego co mi napisałeś kodu to kompilator wypluwa mi błąd przy tworzeniu obiektu C:

 

c = new C(this);

 

odnośnie "Braku dopasowania funkcji dla wywołania C::C(A* const); "

rozumiem, że konwersję można spróbować zrobić ale też mi to nie chce działać.

 

Natomiast co do samego wskaźnika, to można w sekcji prywatnej klasy C stworzyć wskaźnik np. "void* baseClass;" i w konstruktorze przypisać:

this->baseClass = base;

 

po czym każdorazowe użycie dostępu do nadklasy :) wiąże się z takową wiązanką kodu:

A* aClass = static_cast<A>(this->baseClass);
//  aClass->b->test();

 

co można w prywatną funkcję obudować.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Tak korzystam z tego czasami i to działa. Podaj kod, oraz to co Ci zwraca kompilator - dokładnie, bo coś masz widocznie nie tak.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

OK, dam przykład który wywala w konstruktorze klasy w pliku AClass.cpp z komunikatem:

no matching function for call to 'BClass::BClass(AClass* const)'|

this->bClass = new BClass(this);

A to całość:

main.cpp

#include "AClass.h"

int main()
{
   AClass* aClass = new AClass;

   delete aClass;
}

AClass.h

#ifndef ACLASS_H
#define ACLASS_H

#include "BClass.h"
#include "CClass.h"

class AClass
{
   public:
       AClass();
       virtual ~AClass();
       BClass* getBClass();
       CClass* getCClass();
   protected:
   private:
       BClass* bClass;
       CClass* cClass;
};

#endif // ACLASS_H

AClass.cpp

#include "AClass.h"

AClass::AClass()
{
   this->bClass = new BClass(this);
   this->cClass = new CClass(this);
}

AClass::~AClass()
{
   //dtor
}

BClass* AClass::getBClass();
{
   return this->bClass;
}

Class* AClass::getCClass();
{
   return this->cClass;
}

BClass.h

#ifndef BCLASS_H
#define BCLASS_H

class pAClass;

class BClass
{
   public:
       BClass(pAClass* _AClass_);
       virtual ~BClass();
       void testFunction();
   protected:
   private:
       pAClass* _aClass;
};

#endif // BCLASS_H

BClass.cpp

#include "AClass.h"

BClass::BClass(pAClass* _AClass_)
:_aClass(_AClass_)
{
   // this->_aClass = _AClass_;  /\ UP /\
}

BClass::~BClass()
{
   //dtor
}

void BClass::testFunction()
{
   std::cout << "test Function message";
}

CClass.h

#ifndef CCLASS_H
#define CCLASS_H


class pAClass;
class CClass
{
   public:
       CClass(pAClass* _AClass_);
       virtual ~CClass();
   protected:
   private:
       pAClass* _aClass;
};

#endif // CCLASS_H

CClass.cpp

#include "AClass.h"

CClass::CClass(pAClass* _AClass_)
:_aClass(_AClass_)
{
//  this->_aClass = _AClass_; /\ UP /\
  AClass* myClass = static_cast<AClass>(this->_aClass);
  myClass->getBClass()->testFunction();
}

CClass::~CClass()
{
   //dtor
}

 

To oczywiście przykład kodu zmodyfikowany na potrzeby metody "po Twojemu" :)

Moja wiedza na temat C++ nie jest wielka więc miło będzie się czegoś dowiedzieć

 

Pozdrawiam.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Z poprzednich Twoich wypowiedzi napisałeś:

class A;
class C
{
...

 

więc to jest zamiast "class A;"

Sam to zaproponowałeś.

Ps. średniki są na zakończenie instrukcji, co w tym złego? I proszę napisz gdzie widzisz nadmiar średników ?

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Tak napisałem i tak ma być, to było class A, do twojego class A - ma dokładnie tak samo się nazywać! Czyli w przypadku opisanym w drugim przykładzie, co dałes ma być class AClass;

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

A to wybacz proszę :]

Tak działa wszystko tak jak powinno, wystarczyło wspomnieć, że to ma być prototyp.

A o prototypach w C++ zapomniałem.

A średniki nie zauważyłem przy pisaniu, w pliku AClass.cpp jest nadmiar przy metodach getBClass() i getCClass().

Kod na szybko pisany.

 

 

 

 

Dzięki za pomoc.

Pozdrawiam.

Udostępnij ten post


Link to postu
Udostępnij na innych stronach

Bądź aktywny! Zaloguj się lub utwórz konto

Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony

Utwórz konto

Zarejestruj nowe konto, to proste!

Zarejestruj nowe konto

Zaloguj się

Posiadasz własne konto? Użyj go!

Zaloguj się
Zaloguj się, aby obserwować  

×