Wewnętrzny typ W C++ - dobry czy zły styl?
Coś, co ostatnio często robię, to deklarowanie typedefów związanych z konkretną klasą wewnątrz tej klasy, tj.
class Lorem
{
typedef boost::shared_ptr<Lorem> ptr;
typedef std::vector<Lorem::ptr> vector;
//
// ...
//
};
Typy te są następnie używane gdzie indziej w kodzie:
Lorem::vector lorems;
Lorem::ptr lorem( new Lorem() );
lorems.push_back( lorem );
Powody, dla których to lubię:
- redukuje szum wprowadzany przez szablony klas,
std::vector<Lorem>
staje sięLorem::vector
, itd.
W tym celu należy skontaktować się z Działem Obsługi Klienta pod numerem telefonu + 48 22 222 50 00, a następnie skontaktować się z Działem Obsługi Klienta pod numerem telefonu + 48 22 222 50 00. wektor.
- pozwala na zmianę implementacji - tzn. jeśli lorem musi zostać zmieniony, aby być liczonym w sposób intruzywny (poprzez
boost::intrusive_ptr
) na późniejszym etapie, to miałoby to minimalny wpływ na kod. - myślę, że wygląda "ładniej" i jest prawdopodobnie łatwiejsza do odczytania.
Powody, dla których mi się to nie podoba:
- czasami występują problemy z zależnościami - jeśli chcesz osadzić, powiedzmy,
Lorem::vector
w innej klasie, ale tylko potrzebujesz (lub chcesz) forward declare Lorem (w przeciwieństwie do wprowadzania zależności od jego pliku nagłówkowego) w końcu musisz użyć jawnych typów (np.boost::shared_ptr<Lorem>
zamiastLorem::ptr
), co jest trochę niespójne.
[16]}to może nie być zbyt powszechne, a zatem trudniejsze do zrozumienia?
Staram się być obiektywny z moim stylu kodowania, więc byłoby dobrze, aby uzyskać kilka innych opinii na ten temat, więc mogę przeanalizować moje myślenie trochę.
9 answers
Uważam, że jest to świetny styl i sam go używam. Zawsze najlepiej jest ograniczyć zakres nazw tak bardzo, jak to możliwe, a użycie klas jest najlepszym sposobem, aby to zrobić w C++. Na przykład, Biblioteka Standardowa C++ intensywnie wykorzystuje typedefs w klasach.
Służy jako oświadczenie woli - w powyższym przykładzie Klasa Lorem jest przeznaczony do liczenia odniesienia via boost:: shared_ptr i przechowywane w wektor.
To jest dokładnie to, co robi , a nie .
Jeśli widzę 'Foo:: Ptr' w kodzie, absolutnie nie mam pojęcia, czy to shared_ptr czy Foo* (STL ma ::pointer typedefs, które są T*, pamiętaj) czy cokolwiek. Esp. jeśli jest to wskaźnik współdzielony, w ogóle nie podaję typedef, ale zachowaj shared_ptr używa jawnie w kodzie.
Właściwie, rzadko używam typedefów poza Metaprogramowaniem szablonów.
STL robi tego typu rzeczy cały czas
Konstrukcja STL z pojęciami zdefiniowanymi w kategoriach funkcji Członkowskich i zagnieżdżonych typów jest historycznym zaułkiem, nowoczesne biblioteki szablonów używają wolnych funkcji i klas cech (por. Boost.Graf), ponieważ nie wykluczają one wbudowanych typów z modelowania koncepcji oraz dlatego, że sprawia łatwiejsze dostosowanie typów, które nie zostały zaprojektowane z myślą o pojęciach bibliotek szablonów.
Nie używaj STL jako powodu do popełniania tych samych błędów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-12 14:10:29
Typedefs to te, którepolicy based design and traits zostały zbudowane w C++, więc moc generycznego programowania w C++ wynika z samych typedefów.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 08:44:36
Typdefy są zdecydowanie dobrym stylem. I wszystkie twoje "powody, które lubię" są dobre i poprawne.
O problemach z tym. Deklaracja nie jest świętym graalem. Możesz po prostu zaprojektować swój kod, aby uniknąć wielopoziomowych zależności.
Możesz przenieść typedef poza klasę, ale Class:: ptr jest o wiele ładniejsza niż ClassPtr, że tego nie robię. Jest tak jak w przypadku przestrzeni nazw, jak dla mnie-rzeczy pozostają połączone w ramach zakresu.
Sometimes I did
Trait<Loren>::ptr
Trait<Loren>::collection
Trait<Loren>::map
I może być domyślna dla wszystkich klas domenowych i z pewną specjalizacją dla niektórych.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 08:35:36
STL robi tego typu rzeczy cały czas - typedefs są częścią interfejsu dla wielu klas w STL.
reference
iterator
size_type
value_type
etc...
Są typedefami, które są częścią interfejsu dla różnych klas szablonów stl.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 08:36:43
Kolejny głos za dobrym pomysłem. Zacząłem to robić, pisząc symulację, która musiała być efektywna, zarówno w czasie, jak i przestrzeni. Wszystkie typy wartości miały typedef Ptr, który zaczynał się jako wskaźnik współdzielony boost. Następnie zrobiłem profilowanie i zmieniłem niektóre z nich na natrętny wskaźnik boost bez konieczności zmiany żadnego kodu, w którym te obiekty były używane.
Zauważ, że działa to tylko wtedy, gdy wiesz, gdzie będą używane klasy, i że wszystkie zastosowania mają te same wymagania. Nie używałbym tego na przykład w kodzie biblioteki, ponieważ nie można znać podczas pisania biblioteki kontekstu, w jakim będzie ona używana.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 14:13:54
Zalecam przeniesienie tych wpisów poza klasę. W ten sposób usuwa się bezpośrednią zależność od współdzielonych klas wskaźnika i wektora i można je dołączać tylko wtedy, gdy jest to potrzebne. Chyba, że używasz tych typów w swojej klasie implementacji, uważam, że nie powinny one być typami wewnętrznymi.
Powody, dla których to lubisz, są nadal dopasowane, ponieważ są rozwiązywane przez aliasing typu poprzez typedef, a nie przez deklarowanie ich wewnątrz twojej klasy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 08:28:24
Obecnie pracuję nad kodem, który intensywnie używa tego typu typedefów. Jak na razie jest dobrze.
Ale zauważyłem, że są dość często iteracyjne typy, definicje są podzielone na kilka klas i nigdy nie wiadomo, z jakim typem masz do czynienia. Moim zadaniem jest podsumowanie wielkości niektórych złożonych struktur danych ukrytych za tymi typedefami - więc nie mogę polegać na istniejących interfejsach. W połączeniu z trzema do sześciu poziomów zagnieżdżonych przestrzeni nazw, a następnie staje się mylące.
Więc przed ich użyciem należy rozważyć kilka punktów
- czy ktoś jeszcze potrzebuje tych wpisów? Czy klasa jest często używana przez inne klasy?
- czy skracam użycie czy ukrywam klasę? (W przypadku ukrycia można również pomyśleć o interfejsach.) Czy inni ludzie pracują z kodem? Jak oni to robią? Czy będą myśleć, że to łatwiejsze, czy będą zdezorientowani?
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-18 08:28:57
Kiedy typedef jest używany tylko w samej klasie (tzn. jest zadeklarowany jako prywatny) myślę, że to dobry pomysł. Jednak z dokładnie tych powodów, które podajesz, nie użyłbym go, gdyby typedef musiał być znany poza klasą. W takim razie polecam przenieść ich poza klasę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-17 08:31:08