Zmienna dostępna w całej klasie (obiekcie)

0

Cześć, mam pytanie:
Mam klasę główną, która składa się z wielu mniejszych obiektów, które również składają się z innych obiektów a tamte z jeszcze innych. Może to wyglądać np. tak:

class Klasa_głowna
{
Klasa2 klasa2[100];
int zmienna_glob1;
double zmienna_glob2;
//...
};
class Klasa2
{
Klasa3 klasa3[50];
//...
};
//itd.

Moje pytanie brzmi: jak zrobić, żeby zmienna zmienna_glob1 oraz zmienna_glob2 była dostępna we wszystkich obiektach wewnątrz klasy głównej - tzn. w każdym obiekcie klasy Klasa2, Klasa3 itd?

Chodzi mi o to, by nie używać zmiennej statycznej ani globalnej (bo mogą być np. dwa obiekty Klasy_glowna, które mają różne wartości tych zmiennych.
Używanie w każdym obiekcie wewnętrznym wskaźnika do tej zmiennej jest bardzo kłopotliwe (przy tworzeniu nowego obiektu trzeba go jakoś przekazywać, a takich zmiennych jest więcej...)
Problematyczne jest również przekazywanie wszystkich tych zmiennych w funkcji, bo wówczas funkcja ma wówczas bardzo dużo parametrów...

Czy jest jeszcze jakiś sposób, by obiekty wewnątrz klasy miały dostęp do zmiennych klasy głównej?

0

Mogę się mylić - sam się jeszcze uczę ale ja bym opakował te 'globalne zmienne' w czystko abstrakcyjną klasę i użył jej jako interfejs.

0
#include <iostream>
using namespace std;

class Base
{
public:
	Base(int mAV): myAwesomeVariable(mAV) { ; }
	
protected:
	int myAwesomeVariable;
};

class Derived : public Base
{
public:
	Derived(int mAV): Base(mAV) { ; }
	
	int getMyAwesomeVariable() const { return myAwesomeVariable; }
};

int main() {

	Derived d(10);
	cout << d.getMyAwesomeVariable();
	return 0;
}

http://ideone.com/ZYQYrU

0

No tak, ale ja potrzebuję klasy, która składa się z kilku obiektów innej klasy -> więc tu chyba nie pasuje dziedziczenie.
Dodatkowo są to raczej niezależne klasy tzn. nie jestem pewien czy nawet logiczne jest dziedziczyć jeden po drugim. Ma tylko kilka wspólnych elementów a raczej takich, do których musi mieć dostęp ta klasa bazowa...

No chyba, że można w klasie pochodnej utworzyć tablicę obiektów klasy bazowej?!? Ale dla mnie to trochę dziwne rozwiązanie... A co wy o tym myślicie?

Ok, składniowo chyba jest ok, ale chyba to nie rozwiązuje mojego problemu, bo jak utworzę w klasie bazowej zmienną, która będzie dziedziczona, a następnie utworzę kilka obiektów tej klasy to będę miał w klasie pochodnej N takich zmiennych.
Natomiast mi chodziło, by w klasie "pochodnej" (tzn. tej nadrzędnej) mieć jedną zmienną, która będzie widoczna w każdym obiekcie podrzędnym.

0

Jeśli dobrze zrozumiałem o co ci chodzi, to się nie da. To po prostu nie ma sensu. Skąd Klasa2 miałaby wiedzieć czy akurat jest wewnątrz Klasy Głownej? Przyklad: Klasa Główna to człowiek, a Klasa2 to atom. Skąd atom miałby wiedzieć czy jest częścią człowieka czy kamienia? :D Możesz co najwyżej zrobić 'atomowi' referencję do 'człowieka' w konstruktorze, ale chyba rozumiesz że to nie ma sensu, nie? Przemyśl jeszcze raz czy na pewno potrzebujesz tych zmiennych.

0

Innymi słowy:

class Base
	{
	public:
	double variable;
	Inside inside[10];	//każdy obiekt z tej tablicy powinien mieć dostęp do zmiennej variable
	};
class Inside
	{
	//... <- jakieś funkcje, które korzystają m.in. ze zmiennej variable, która jest zadeklarowana w klasie Base
	};

dodanie znacznika <code class="cpp"> - fp

0
  1. sorry, zapomniałem dać kod w znaczniki...
  2. @Sinity chyba rzeczywiście masz rację... Muszę to jeszcze przemyśleć!

Z drugiej strony obiekt tej klasy może być tylko w tej klasie bazowej - nie przewiduję wstawiania jej do innych klas (jest to tak jakby klasa wewnętrzna)...

3

Huh, fajny problem :)

Jedynym poprawnym rozwiązaniem, które przychodzi mi do głowy, to po prostu przekazać w konstruktorze klasy Base() wszystkim inside() adres zmiennej variable, np.:

Base::Base() {
  for(int i = 0; i < sizeof(this->inside) / sizeof(this->inside[0]); i++)
    this->inside[i].SetVariableAddr(&this->variable);
}

class Inside {
  private:
    double *super;
  //... you get the picture :) ...
}

Oczywiście najwygodniej będzie to ze zmiennej "variable" zrobić strukturę, tak, żeby tylko jeden pointer przekazywać (i potem robić jakieś super->asdf).

Z mniej poprawnych, ale technicznie (chyba implementation defined) rozwiązań, można zrobić coś w tym stylu:

class Base {
  unsigned int magic;
  double variable;
  ...
  Inside inside[10];
  ...

  Base() { this->magic = 0x0badc0d3; }
  
  class Inside {
    // ...
    double* getVariable() {
      unsigned char *p = (unsigned char*)this;
      // te poszukiwania można zscacheować ofc
      for(;;p--) {
        if(*p != 0xd3) continue;
        if(memcmp(p, "\xd3\xc0\xad\x0b", 4) != 0) continue;
        p += 4;
        return (double*)p;
      }

      public:
        void asdf() { printf("variable=%f\n", *this->getVariable()); }
    }
...

To powinno działać na dowolnych little endianach, ale chyba nie do końca jest zgodne ze standardem (ale być może jest zgodne ze standardem rozszerzonym o specyfikacje implementacji).

dodanie znaczników <code class="cpp"> - fp

0

Najbardziej mi się podoba zapis:

magic = 0x0badc0d3;

Na pierwszy rzut oka nie wiedziałem o co chodzi (co to za adres?) aż w końcu doczytałem ;-)

Ten pierwszy sposób mniej więcej właśnie obecnie stosuję, ale nie jest on zbyt wygodny.
Zapomniałem również poinformować, że obiekty tworzone są dynamicznie i przy tworzeniu nowych kilku obiektów wewnętrznych jestem zmuszony przekazać jakoś wszystkie te wskaźniki... Naturalnie stworzyłem strukturę z przekazywanymi wskaźnikami ;)

Ten drugi sposób to już jest jakiś hardcore jak dla mnie ;-)

Myślałem również nad klasami zagnieżdżonymi - niestety problem jest taki, że klasa najniżej w hierarchii ma kilkaset linijek kodu, więc jak będę zagnieżdżał każdą klasę to po chwili cyrylice będzie łatwiej czytać...

Myślałem, że jest możliwość tylko zadeklarowania klasy wewnętrznej a jej definicję napisania w innym pliku np. tak:

class Base
{
public:
class derived; //jeszcze jest dopuszczalne
derived x; //już nie jest ok...
//...
};

class derived
{
//...
};

Zastanawiam się również nad takim zapisem:

class Base
{
public:
#include "derive.h" //zaincludowanie wewnątrz klasy -> czyli będzie to klasa wewnętrzna (?!?)
derive x; //to jest już dopuszczalne ;-)
}

Ale to tylko komplikuje cały kod... Co o tym myślicie? ;-)

By the way - dzięki wszystkim za wypowiedzi!

1

Zapomniałem również poinformować, że obiekty tworzone są dynamicznie i przy tworzeniu nowych kilku obiektów wewnętrznych jestem zmuszony przekazać jakoś wszystkie te wskaźniki...

Hmm, robisz to raz w konstruktorze, więc nie brzmi to super niewygodnie (w sumie w przykładzie w moim poprzednim poście były to 2 linie w konstruktorze).
Alokacja dynamiczna w niczym tu nie przeszkadza.

Ad reszta co pisałeś - wystarczy, że zrobisz:

#include "derive.h"
class Base
{
  public:
  derive x;
}

dodanie znacznika <code class="cpp"> - fp

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