Klasy zagnieżdżone - jaki jest sens ich stosowania?

Klasy zagnieżdżone - jaki jest sens ich stosowania?
0

Czy może mi ktoś wytłumaczyć jaki jest sens stosowania klas zagnieżdżonych?
Jakie są zalety takiego tworzenia klas? Co mi to daje? Przeczytałem, że czasami może to być wygodniejsze, ale póki co jakoś nie dostrzegam tej wygody...
Z góry dziękuję za wyjaśnienie

satirev
  • Rejestracja:prawie 14 lat
  • Ostatnio:około 4 lata
0

Wszędzie tam, gdzie dany typ jest na tyle zależny od innego typu, że nie ma sensu definiować go poza tym drugim typem. Dobrym przykładem mogą być tutaj iteratory.

Lectre
  • Rejestracja:około 10 lat
  • Ostatnio:ponad 6 lat
  • Lokalizacja:Warszawa
  • Postów:293
0

W C++ jest to jedynie ukrywanie implementacji, Java daje tutaj trochę więcej możliwości. Ogólnie to, co nie jest bezpośrednio potrzebne na zewnątrz zamykasz w klasie zagnieżdżonej.

spartanPAGE
Albo anonimowej przestrzeni nazw
IE
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 7 lat
  • Postów:32
0

Ot po prostu ułatwiają organizację kodu. Np. piszesz jakąś strukturę danych (dla przykładu założę, że to hash mapa) i potrzebujesz wewnątrz niej dodatkowej struktury, która będzie trzymać parę klucz-wartość. Użytkownik nie powinien mieć do niej dostępu (bo po co mu to?), zatem możesz umieścić taką strukturkę w prywatnej części klasy i po kłopocie.

Inny przykład to wszelkiego rodzaju kontenery z biblioteki standardowej (np. vector, map). Każdy z nich ma w sobie iterator. I o ile całkowicie możliwe technicznie byłoby umieszczenie obu w przestrzeni std, to znacznie wygodniej jest, gdy iterator jednak siedzi w klasie kontenera. Po pierwsze łatwiej się pisze, bo masz od razu dostęp do innych prywatnych elementów klasy, wiesz dla jakiej klasy piszesz iterator (gdybyś pisał go oddzielnie, to musiałbyś albo robić coś w stylu vector_iterator<T>, map_iterator<T>, albo podawać typ kolekcji jako argument szablonu - oba niezbyt fajne). Poza tym jest też wygodniejsze dla użytkownika, bo w swoim kodzie może zrobić:

Kopiuj
typedef map<string, string> Collection;

i potem używać typu Collection, a typ iteratora to po prostu Collection::iterator - i nagle okazuje się, że zmiana std::map na std::unordered_map jest trywialna. W przeciwieństwie do hipotetycznej sytuacji, gdy mamy std::map i std::map_iterator.

0

Dzięki wszystkim za odpowiedzi.
Mam jeszcze jedno pytanie: czy da się w klasie wewnętrznej odwołać do metody lub pola klasy zewnętrznej?

stryku
  • Rejestracja:ponad 11 lat
  • Ostatnio:ponad rok
  • Postów:607
0

Jeżeli masz kod, który musi coś takiego zrobić to jest to źle zaprojektowane. I najlepiej to przeprojektować niż brnąć.

edytowany 1x, ostatnio: stryku
n0name_l
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 4 lata
  • Postów:2412
0

Mam jeszcze jedno pytanie: czy da się w klasie wewnętrznej odwołać do metody lub pola klasy zewnętrznej?

Da się.

Kopiuj
#include <iostream>
using namespace std;

struct Foo {
	struct Bar {
		int a, b;
	};
	
	Bar bar() {
		return Bar { x, y };	
	}
	
	int x, y;
};

int main() {
	Foo f { 123, 321 };
	Foo::Bar b = f.bar();
	cout << b.a << endl;
	return 0;
}
IE
W którym miejscu z klasy wewnętrznej (Bar) odwołujesz się do pola/metody klasy zewnętrznej (Foo)?
n0name_l
W tym, w którym przekazuje to pola do konstruktora klasy zagnieżdżonej. Ja rozumiem, że to nie jest bezpośrednio, ale jednak. Zresztą, tak samo wygląda kwestia z iteratorami kolekcjami w std np.
0

Dzięki @n0name_l ale chyba nie do końca o to mi chodziło.
Zastanawiałęm się, czy jest możliwość zrobić coś w tym stylu:

Kopiuj
class A
	{
	public:
		class B
			{
			public:
				int fun()
					{
					return a;
					}
			};

		B b;
		int a;
	};

Niestety powyższy kod się nie kompiluje ;-(.
Próbowałem również dodać operator zakresu tj. return A::a - bez powodzenia.

IE
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 7 lat
  • Postów:32
0

Takie coś nie ma prawa działać, bo obiekty klasy B mogą istnieć niezależnie od obiektów klasy A. Można np. stworzyć:

Kopiuj
std::vector<A::B> arr(32);

I co w takim wypadku oznaczałoby return a;

Kopiuj
?

Możesz za to dodać dodatkowy argument konstruktora klasy B - referencja do klasy A, a następnie odwoływać się za pomocą jej do pól klasy A. Dodatkowo możesz ten konstruktor uczynić prywatnym, by tylko klasa A mogła tworzyć obiekty typu B (i przy okazji dorzucać do konstruktora referencje do samej siebie).
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)