Instancje klasy B korzystają z pól klasy A

0

Klasa A posiada wektor i zapełnia go dużą ilością danych, a klasa B ma bardzo dużo instancji i każda z instancja korzysta z wektora z klasy A.
Chciałbym żeby to działało mniej więcej tak:

class A
{
private:
	std::vector<sf::Texture> tab;
public:
	void zapelnijTab()
	{
		tab.resize(1000);
		for (int i = 0; i < 1000; i++)
			tab[i].loadFromFile("jakastextura");
	}
};
class B
{
public:
	B() {}
	sf::Sprite sprite;
	void ustawTexture(int x)
	{
		sprite.setTexture(tab[x]);
	}
	sf::Sprite getSprite()
	{
		return sprite;
	}
}

B bety[100000];
sf::RenderWindow window;
while (true)
{
	for (int i = 0; i < 100000; ++i)
	{
		ustawTexture(losowaTextura);
		window.draw(bety[i]->getSprite());
	}
}

Jak to dobrze zaimplementować?

2

Chcesz w jednej klatce wywoływać 100tys. razy setTexture i draw? Ja bym to przemyślał.

E:
Nie rozumiem w czym problem. Do klasy A dodajesz funkcję, która zwraca teksturę spod danego indeksu i wsio.

0

Do B możesz przekazać wskaźnik na obiekt A, możesz zaimplementować A jako zmienną statyczną w B lub jako singleton. Możesz też odwołać się bardziej pośrednio (przez dodatkowe klasy i/lub funkcje).
Poczytaj i zdecyduj co będzie najlepsze w Twoim przypadku. Na wybór wpływa wiele czynników i nie ma "jedynej słusznej" implementacji.

0

Witam.

Po zmianach na forum nie mogę założyć własnego wątku (brak reputacji), więc zgodnie z instrukcjami, dopisuję się do już istniejącego, których trochę (chyba?) zahacza o mój problem. Absurdalne to, ale co zrobić... No ale przechodząc do rzeczy:

Czy istnieje możliwość dziedziczenia z wielu klas jednocześnie, ale w taki sposób, by ta klasa dziedzicząca nie stawała się "śmietnikiem" łączącym zawartość wszystkich tych klas bazowych, ale z zastosowaniem jakichś podgrup?

Chodzi mi o coś takiego:

class BaseA
{
public:   
   int Width;
};

class BaseB
{
public:
   int Height;
};

class Child : public BaseA, public BaseB
{

};

Dostęp do np. zmiennej Width będzie wyglądał tak:

Child Ch;
Ch.Width = 46;

A ja chciałbym to mieć bardziej zorganizowane, np. w taki sposób:

Child Ch;
Ch.BaseA.Width = 46;

Tak, żeby było wyraźnie widać co z czego pochodzi. Da się to jakoś zrobić?

Jeżeli nie konkretnie w taki sposób, to może da się to załatwić jakoś inaczej? Zależy mi przede wszystkim na "uporządkowaniu" klasy poprzez podzielenie jej na kategorie (podgrupy). Np. zmienne i funkcje dotyczące grafiki 2D w osobnej zakładce, 3D w osobnej itp. A chcę to zamknąć w jednej klasie, żeby mieć jedną klasę i jeden konstruktor, a nie 10-12 osobnych.

0

@Crow: technicznie, możesz zrobić

dynamic_cast<BaseA*>(&Ch)->Width = 46;

ale w ogóle udostępnianie takich pól do bezpośredniej modyfikacji to jest antypattern.

Pamiętaj o SRP (single responsibility principle), klasa powinna odpowiadać tylko za jedną kwestię. Jeśli chcesz mieć w niej coś co odpowiada za 2D i za 3D, to jak to w ogóle się łączy? Powinno być w ogóle w jednej klasie? Jak dla mnie zdecydowanie nie. A skoro chcesz na siłę robić wbrew dobrym zasadom to spodziewaj się wielu problemów potem.

Poza tym nawet jeśli dziecko dziedziczy po wielu klasach bazowych i ma tylko jeden konstruktor, to każda klasa bazowa również wymaga takiego konstruktora dla siebie, który musi i tak powstać, chyba, że planujesz ręcznie przypisywać tak jak powyżej wartości zmiennych, co prowadzi do bardzo nieczytelnego kodu.

0

@enedil:

Póki co mam to zorganizowane tak:

class Base
{
	class ncGraphics2D
	{
		Base& Parent;
	public:
		ncGraphics2D(Base& rParent) : Parent(rParent)
		{

		}
	};

        class ncGraphics3D
	{
		Base& Parent;
	public:
		ncGrapics3D(Base& rParent) : Parent(rParent)
		{

		}
	};
	int ID;
	float Data;
	//itd.
public:
	ncGraphics2D Graphics2D;
	ncGraphics3D Graphics3D;
	//itd.
        Base() : Graphics2D(*this), Graphics3D(*this) //itd.
	{

	}
};

Dzięki takiej konstrukcji wystarczy stworzyć instancję klasy Base, która w konstruktorze "produkuje" i przechwytuje wszelkie niezbędne zasoby, np. uchwyty okien, informacje dotyczące rozdzielczości ekranu, odświeżania monitora, schematu kolorów itd. i są one wszystkie przechowywane w prywatnej sekcji Base. Natomiast "subklasy" (jak Graphics2D czy Display) za pomocą podawanej im w konstruktorze referencji do klasy bazowej (Parent) mają dostęp do tych zasobów (bo są zagnieżdzone) i mogą z nich swobodnie korzystać. Ułatwia mi to sprawę o tyle, że nie muszę osobno tworzyć 10 subklas i podawać każdej z nich referencji do poszczególnych obiektów (np. uchwytów okien) albo kopii różnych danych (np. informacji o rozdzielczości czy buforze ekranu). Tworzę tylko `Base', a cała reszta jest "zautomatyzowana".

Czy mój pomysł jest OK? Da się to rozwiązać jakoś lepiej?

0

Czemu nie zrobić zwykłego dziedziczenia?
Albo zwyczajnie użyć friend?

0

Klasa B nie powinna przyjmować Sprite, niech przyjmuje kod opisujący co niby ma się wyświetlić. Tu bardziej liczy się ta informacja niż konkretny zasób.

Natomiast ten wektor przekazałbym do kodu, który zajmuje się rysowaniem. Kod rysujący dostaje obiekt do narysowania, i odczytuje indeks/klucz, wybiera teksturę i rysuje.

Dzięki temu miałbyś kolekcję która jest widoczna tylko w jednym miejscu. Będziesz mógł łatwiej kontrolować zakres życia takiej kolekcji, łatwiej będziesz mógł ją podmienić i tak dalej, unikaj wiązania dużej liczby klas ze sobą (bo pewnie poza klasą B, będzie jeszcze C, D i podobne które maja logikę i powiązania z teksturami), w przeciwnym razie uzyskasz kolekcję o zasięgu globalnym, co ogólnie podniesie Ci złożoność w projekcie i utrudni utrzymanie.

0

Czy mój pomysł jest OK? Da się to rozwiązać jakoś lepiej?

Spróbuj minimalizować zależności pomiędzy klasami. Czyli w Twoim przypadku wszystkie zmienne/metody z których korzysta tylko i wyłącznie klasa Graphics2D/3D powinny znaleźć się wewnątrz niej. Z drugiej strony klasy Graphics2D/3D powinny mieć dostęp tylko do tych zmiennych/metod które używają/współdzielą, a nie do wszystkiego co znajduje się w klasie nadrzędnej.
Przykład:

class GraphicsBase
{
protected:
    vector<int>& signal;
public:
    GraphicsBase( vector<int>& _signal ): signal {_signal} {}
};

class Graphics2D : public GraphicsBase
{
public:
    Graphics2D( vector<int>& _signal ): GraphicsBase{_signal} {}
};

class Graphics3D : public GraphicsBase
{
public:
    Graphics3D( vector<int>& _signal ): GraphicsBase{_signal} {}
};

class Engine
{
   vector<int> signal;
public:
   Graphics2D view2D {signal};
   Graphics3D view3D {signal};
};
2
Crow napisał(a):

Witam.

Czy istnieje możliwość dziedziczenia z wielu klas jednocześnie, ale w taki sposób, by ta klasa dziedzicząca nie stawała się "śmietnikiem" łączącym zawartość wszystkich tych klas bazowych, ale z zastosowaniem jakichś podgrup?

Mi pachnie, że przez kiepskie kursy zostałeś nastawiony jedynie na dziedziczenie. A dziedziczenie to dalece nie jest 100% programowania obiektowego, a wręcz dośc niewiele. Np kompozycja.

class Config {
}

class FunkcjonalnośćX {
   const Config * config;
   FunkcjonalnośćX (const Config * conf) config(conf) {}
}

Chodzi mi o coś takiego ...

Przykład wydaje się wręcz chory. Jak dasz bardziej realistyczny, W TYM Z REALNYMI NAZWAMI klas zamiast ClassA, pogadamy.
Powtórzę, co koledzy mówili o ZAKRESIE ODPOWIEDZIALNOŚCI klas, a dobra nazwa to wyraża (a odwrotnie: problem z daniem dobrej nazwy wskazuje na problem z pomysłem)

Jeżeli nie konkretnie w taki sposób, to może da się to załatwić jakoś inaczej? Zależy mi przede wszystkim na "uporządkowaniu" klasy poprzez podzielenie jej na kategorie (podgrupy). Np. zmienne i funkcje dotyczące grafiki 2D w osobnej zakładce, 3D w osobnej itp. A chcę to zamknąć w jednej klasie, żeby mieć jedną klasę i jeden konstruktor, a nie 10-12 osobnych.

Pachnie jakbyś chciał mieć jedną mega-klasę - albo ja Cię nie rozumiem.
Klasa NIE JEST śmietnikiem na wszystko co wymyśliłem.

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