मैं समझता हूं कि सार्वजनिक विरासत के साथ यह सामान्य रूप से सुरक्षित है, क्योंकि delete
बेस क्लास पॉइंटर में संकलक केवल बेस क्लास के विनाशक को कॉल करने के लिए कोड उत्पन्न करता है, और व्युत्पन्न वर्ग के किसी को नहीं कहा जाता है।क्या यह गैर-वर्चुअल विनाशक वाले वर्ग से निजी रूप से उत्तराधिकारी है?
लेकिन निजी वंशानुक्रम के लिए ग्राहक को एक आधार वर्ग सूचक के लिए एक व्युत्पन्न वर्ग सूचक डाली नहीं कर सकते हैं (जैसा कि निजी वंशानुक्रम मॉडल नहीं है संबंध-एक है), इसलिए delete
हमेशा व्युत्पन्न वर्ग के सूचक पर प्रयोग किया जाता है, और संकलक यह देखने में सक्षम होना चाहिए कि एक बेस क्लास भी है और इसके विनाशक को बुलाओ।
#include <iostream>
struct BaseVirtual
{
virtual ~BaseVirtual()
{
std::cout << "BaseVirtual's dtor" << '\n';
}
};
struct BaseNonVirtual
{
~BaseNonVirtual()
{
std::cout << "BaseNonVirtual's dtor" << '\n';
}
};
struct DerivedPrivVirtual: private BaseVirtual
{
static void f()
{
BaseVirtual * p = new DerivedPrivVirtual;
delete p;
}
~DerivedPrivVirtual()
{
std::cout << "DerivedPrivVirtual's dtor" << '\n';
}
};
struct DerivedPrivNonVirtual: private BaseNonVirtual
{
static void f()
{
BaseNonVirtual * p = new DerivedPrivNonVirtual;
delete p;
}
~DerivedPrivNonVirtual()
{
std::cout << "DerivedPrivNonVirtual's dtor" << '\n';
}
};
int main()
{
std::cout << "With explicit derived pointer type:" << '\n';
{
DerivedPrivVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
DerivedPrivNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;
delete derivedPrivVirtual;
delete derivedPrivNonVirtual;
}
std::cout << '\n';
std::cout << "With base pointer type:" << '\n';
{
// Client code can't cast Derived to Base when inherit privately.
//BaseVirtual * derivedPrivVirtual = new DerivedPrivVirtual;
//BaseNonVirtual * derivedPrivNonVirtual = new DerivedPrivNonVirtual;
//delete derivedPrivVirtual;
//delete derivedPrivNonVirtual;
}
std::cout << '\n';
std::cout << "Inside derived class itself:" << '\n';
{
DerivedPrivVirtual::f();
DerivedPrivNonVirtual::f();
}
std::cout << '\n';
std::cout << "With non-dynamic variables:" << '\n';
{
DerivedPrivVirtual derivedPrivVirtual;
DerivedPrivNonVirtual derivedPrivNonVirtual;
}
std::cout << '\n';
}
दोनों जीसीसी 4.7.1 और बजना 3.1 एक ही आउटपुट दे:
मैं इस परीक्षण किए गए। व्युत्पन्न वर्ग कन्स्ट्रक्टर को तब छोड़ दिया जाता है जब व्युत्पन्न वर्ग स्वयं बेस क्लास के लिए व्युत्पन्न क्लास पॉइंटर और delete
पर रखता है।
इस मामले के अलावा जो काफी असामान्य और आसानी से टालने योग्य लगता है (वर्ग का लेखक एकमात्र ऐसा व्यक्ति है जो नुकसान पहुंचा सकता है, लेकिन यह जानता है कि यह किस वर्ग से प्राप्त हुआ है), क्या मैं निष्कर्ष निकाल सकता हूं कि यह सुरक्षित है?
With explicit derived pointer type:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor
With base pointer type:
Inside derived class itself:
DerivedPrivVirtual's dtor
BaseVirtual's dtor
BaseNonVirtual's dtor <-- Only a problem inside the class itself
With non-dynamic variables:
DerivedPrivNonVirtual's dtor
BaseNonVirtual's dtor
DerivedPrivVirtual's dtor
BaseVirtual's dtor
बोनस सवाल: संरक्षित विरासत के बारे में क्या? मुझे लगता है कि नुकसान करने की क्षमता अब सीधे वर्ग के लेखक से प्राप्त नहीं है, बल्कि पदानुक्रम में किसी भी वर्ग के लेखकों के लिए है।
यदि मुझे सही याद है, स्कॉट मेयर्स (प्रभावी सी ++ के लेखक, अधिक प्रभावी सी ++) अभी भी यह भी नहीं जानते कि संरक्षित विरासत का क्या अर्थ है। सार्वजनिक एक "एक-एक" संबंध जहाज है, निजी "कार्यान्वित-इन-टर्म" है, लेकिन संरक्षित है? वह डरावना है। – Borgleader