नेस्टेड कक्षाएं नियमित कक्षाओं की तरह हैं, लेकिन:
- उनके पास अतिरिक्त पहुंच प्रतिबंध है (जैसा कि एक वर्ग परिभाषा के अंदर सभी परिभाषाएं हैं),
- वे दिए गए नामस्थान , जैसे वैश्विक नामस्थान, को प्रदूषित नहीं करते हैं । यदि आपको लगता है कि कक्षा बी कक्षा ए से बहुत गहराई से जुड़ा हुआ है, लेकिन ए और बी की वस्तुएं आवश्यक रूप से संबंधित नहीं हैं, तो आप चाहते हैं कि वर्ग बी ए वर्ग को स्कैन करने के माध्यम से ही सुलभ हो (इसे ए के रूप में संदर्भित किया जाएगा। ::कक्षा)।
कुछ उदाहरण:
सार्वजनिक रूप से घोंसला बनाने वाला वर्ग इसे प्रासंगिक वर्ग के दायरे में रखता है
मान लें कि आपके पास एक वर्ग है SomeSpecificCollection
जो कक्षा की वस्तुओं को एकत्रित करेगा Element
। आप या तो कर सकते हैं:
दो वर्गों की घोषणा करें: SomeSpecificCollection
और Element
- बुरा, क्योंकि नाम "तत्व" एक संभावित नाम संघर्ष का कारण बनने के लिए सामान्य है
एक नेमस्पेस शुरू करें someSpecificCollection
और कक्षाएं घोषित करें someSpecificCollection::Collection
और someSpecificCollection::Element
। नाम संघर्ष का कोई जोखिम नहीं है, लेकिन क्या यह कोई और क्रिया प्राप्त कर सकता है?
दो वैश्विक वर्गों की घोषणा करें SomeSpecificCollection
और SomeSpecificCollectionElement
- जिनमें मामूली कमियां हैं, लेकिन संभवतः ठीक है।
वैश्विक वर्ग SomeSpecificCollection
और वर्ग Element
को इसका नेस्टेड वर्ग घोषित करें । फिर:
- आप किसी भी नाम की गड़बड़ी का जोखिम नहीं उठाते क्योंकि तत्व वैश्विक नामस्थान में नहीं है,
- के कार्यान्वयन में
SomeSpecificCollection
आप सिर्फ Element
, और हर जगह के रूप में संदर्भित करता है SomeSpecificCollection::Element
- जो दिखता है + - के रूप में एक ही 3., लेकिन अधिक स्पष्ट
- यह सरल हो जाता है कि यह "एक विशिष्ट संग्रह का एक तत्व" है, न कि "किसी संग्रह का विशिष्ट तत्व"
- यह दिखाई दे रहा है कि
SomeSpecificCollection
एक वर्ग भी है।
मेरी राय में, अंतिम संस्करण निश्चित रूप से सबसे सहज और इसलिए सबसे अच्छा डिजाइन है।
मुझे तनाव दें - दो वैश्विक वर्गों को अधिक क्रिया नाम देने से कोई बड़ा अंतर नहीं है। यह सिर्फ एक छोटा सा विवरण है, लेकिन यह कोड को अधिक स्पष्ट बनाता है।
एक वर्ग दायरे के अंदर एक और गुंजाइश का परिचय
यह विशेष रूप से टाइपडिफ्स या एनम को पेश करने के लिए उपयोगी है। मैं यहाँ एक कोड उदाहरण पोस्ट करूँगा:
class Product {
public:
enum ProductType {
FANCY, AWESOME, USEFUL
};
enum ProductBoxType {
BOX, BAG, CRATE
};
Product(ProductType t, ProductBoxType b, String name);
// the rest of the class: fields, methods
};
एक तो फोन करेगा:
Product p(Product::FANCY, Product::BOX);
लेकिन जब कोड पूरा होने के प्रस्तावों को देखते हैं Product::
, तो एक बार में सभी संभावित एनम मान (BOX, FANCY, CRATE) सूचीबद्ध हो जाएंगे और यहां एक गलती करना आसान है (C ++ 0x के दृढ़ता से टाइप किए गए एनम की तरह हल करें, लेकिन कभी भी बुरा मत मानना )।
लेकिन अगर आप नेस्टेड वर्गों का उपयोग करते हुए उन एनमों के लिए अतिरिक्त गुंजाइश पेश करते हैं, तो चीजें इस तरह दिख सकती हैं:
class Product {
public:
struct ProductType {
enum Enum { FANCY, AWESOME, USEFUL };
};
struct ProductBoxType {
enum Enum { BOX, BAG, CRATE };
};
Product(ProductType::Enum t, ProductBoxType::Enum b, String name);
// the rest of the class: fields, methods
};
तब कॉल ऐसा लगता है:
Product p(Product::ProductType::FANCY, Product::ProductBoxType::BOX);
फिर Product::ProductType::
एक आईडीई में टाइप करके , किसी को सुझाए गए वांछित दायरे से केवल एनम मिलेगा। इससे गलती करने का जोखिम भी कम हो जाता है।
बेशक यह छोटी कक्षाओं के लिए आवश्यक नहीं हो सकता है, लेकिन अगर किसी के पास बहुत सारे एनम हैं, तो यह क्लाइंट प्रोग्रामर के लिए चीजों को आसान बनाता है।
उसी तरह, यदि आप कभी भी जरूरत पड़ते हैं, तो आप खाके में टाइपफेड का एक बड़ा समूह "व्यवस्थित" कर सकते हैं। यह कभी-कभी एक उपयोगी पैटर्न है।
PIMPL मुहावरा
PIMPL (Pointer से IMPLementation के लिए छोटा) हेडर से एक वर्ग के कार्यान्वयन विवरण को हटाने के लिए उपयोगी एक मुहावरा है। जब भी हेडर के "कार्यान्वयन" भाग में परिवर्तन होता है, तब यह वर्ग 'हेडर के आधार पर वर्गों को फिर से जोड़ने की आवश्यकता को कम करता है।
यह आमतौर पर एक नेस्टेड वर्ग का उपयोग करके लागू किया जाता है:
Xh:
class X {
public:
X();
virtual ~X();
void publicInterface();
void publicInterface2();
private:
struct Impl;
std::unique_ptr<Impl> impl;
}
X.cpp:
#include "X.h"
#include <windows.h>
struct X::Impl {
HWND hWnd; // this field is a part of the class, but no need to include windows.h in header
// all private fields, methods go here
void privateMethod(HWND wnd);
void privateMethod();
};
X::X() : impl(new Impl()) {
// ...
}
// and the rest of definitions go here
यह विशेष रूप से उपयोगी है अगर पूर्ण वर्ग की परिभाषा को कुछ बाहरी पुस्तकालय से प्रकारों की परिभाषा की आवश्यकता होती है जिसमें एक भारी या सिर्फ बदसूरत हेडर फ़ाइल होती है (WinAPI लें)। यदि आप PIMPL का उपयोग करते हैं, तो आप केवल किसी भी WinAPI- विशिष्ट कार्यक्षमता को संलग्न कर सकते हैं .cpp
और इसे कभी भी इसमें शामिल नहीं कर सकते .h
।