2016-09-02 3 views
5

अधिक प्रभावी सी ++ में, एक दिलचस्प बिंदु लाया गया है कि मिश्रित सरणी और बहुरूपता एक बुरा विचार है।मिश्रित सरणी और बहुरूपता के लिए कंपाइलर चेतावनी

class Base { 
    public: 
    Base(int y) : a(y) {} 
    int a; 
}; 

class D : public Base { 
    public: 
    D(int w, int y) : Base(y), c(w) {} 
    int c; 
}; 

std::ostream& operator<<(std::ostream& os, const Base &obj) 
{ 
    os << obj.a << std::endl; 
    return os; 
} 

// This function will work perfectly well if i pass in a `Base` array, 
// but if i pass in `D` array we are going to run into some problems. 
// Namely that `arr[i+1] = &arr[i] + sizeof(Base)` will not progress 
// the array correctly for a `D` array. 
void printArray(const Base arr[]) { 
    for (int i = 0; i < 5; ++i) { 
     std::cout << arr[i]; 
    } 
} 

int main() { 
    D arr[5] = { D(0, 10), D(1, 11), D(2, 12), D(3, 13), D(4, 14)}; 
    printArray(arr); // This compiles without complaint! I understand that the 
        // conversion is legal, but it seems like a warning 
        // about this would be a good idea. 
} 

नोट:: उदाहरण के लिए मैं जानता हूँ कि यह बुरा डिजाइन है, लेकिन एक बिंदु को वर्णन करने के लिए है।

समस्या यहाँ है मैं ऊपर है जब रास्ते में इन दोनों के मिश्रण है कि, जब हम सरणी के माध्यम से पुनरावृति मुद्रित करने के लिए हम सही मात्रा द्वारा सरणी के तत्व प्रगति नहीं होगा (यानी हम sizeof(Base) बजाय sizeof(D) द्वारा ले जाने के)। यह उत्पादन में परिणाम है:

10 
0 
11 
1 
12 

[Live example.]

(और मैं अनुमान लगा रहा हूँ कि operator<< इस तरह बुला शायद यूबी है)।

g++ -std=c++1y -Wall -Weffc++ -pedantic main.cpp के साथ संकलित करते समय मुझे कोई चेतावनी या त्रुटियां नहीं मिलतीं।

  1. क्या कोई संकलक ध्वज है जिसे मैं सक्षम कर सकता हूं जो इस परिदृश्य में एक चेतावनी इंगित करता है?
  2. यदि नहीं, तो क्यों नहीं?
+0

ठीक है, '2 का जवाब) 'यह है कि एक संकलक को लागू करने के लिए" चेतावनियां "अनिवार्य नहीं हैं। आप ऐसी चेतावनी जोड़ने के लिए g ++ के कार्यान्वयनकर्ता से पूछ सकते हैं (यदि यह पहले से मौजूद नहीं है), लेकिन उन्हें किसी भी मानक द्वारा ऐसा करने के लिए मजबूर नहीं किया जाता है। – PaulMcKenzie

+1

@PaulMcKenzie, सच है, लेकिन जीसीसी उनकी चेतावनियों के साथ ऊपर और परे चला जाता है, मैं सोच रहा हूं कि इसका पता लगाने में तकनीकी कठिनाई है या नहीं? –

+0

आपको उन इंजीनियरों से पूछना है जो संकलक को एकसाथ रखते हैं। वहां जवाब "यह एक अच्छा विचार" से कहीं भी हो सकता है "हमारे पास समय नहीं है" "यह पहले से मौजूद है"। – PaulMcKenzie

उत्तर

1

void printArray(const Base arr[])void printArray(const Base* arr) के बराबर है।

किसी ऐसे फ़ंक्शन में D प्रकार का सूचक पास करने के लिए कानूनी है जिसका पैरामीटर const Base* है। तो संकलक कोई चेतावनी नहीं देगा।

+1

कंप्यूटर्स को कानूनी संरचनाओं के लिए चेतावनियां देने की अनुमति है। – jaggedSpire

+0

मुझे पता है कि यह कानूनी व्यवहार है, इसलिए 'int arr [5] है; arr [6] = 10', हमें इसके लिए चेतावनी मिलती है। –

+0

@Ben मान लीजिए कि 'प्रिंटअरे' को किसी तीसरे लाइब्रेरी में परिभाषित किया गया है, और उस लाइब्रेरी में 'D' टाइप 'printArray' के पॉइंटर को पास करने के लिए कोई फ़ंक्शन कॉल नहीं है। कंपाइलर कुछ भी शिकायत नहीं करेगा। हालांकि, जब कोई लाइब्रेरी का उपयोग करता है, और 'd' प्रकार 'printArray' के पॉइंटर को पास करता है। मुझे नहीं लगता कि संकलक के लिए तीसरे लाइब्रेरी में 'printArary' के कार्यान्वयन की जांच करना एक अच्छा विचार है, यह देखने के लिए कि 'printArray' को' बेस 'प्रकार की सरणी की आवश्यकता है या नहीं। –

-1

FYI करें, मिश्रण सरणियों और बहुरूपता अगर बहुरूपता एक हैंडल वर्ग के एक कार्यान्वयन विस्तार के रूप में प्रदान की जाती है किया जा सकता है:

#include <iostream> 
#include <vector> 

// a handle which will happily own any class which implements the concept 
struct Thing 
{ 
    struct concept 
    { 
     virtual void sayHello() const = 0; 
     virtual ~concept() = default; 
    }; 

    Thing(std::unique_ptr<concept> ptr) : _impl(std::move(ptr)) {} 

    void sayHello() const { _impl->sayHello(); } 

    std::unique_ptr<concept> _impl; 
}; 

struct thing_a : Thing::concept 
{ 
    void sayHello() const override { std::cout << "hello from A\n"; } 
}; 

struct thing_b : Thing::concept 
{ 
    void sayHello() const override { std::cout << "hello from B\n"; } 
}; 

int main() 
{ 
    std::vector<Thing> things; 

    things.emplace_back(std::make_unique<thing_a>()); 
    things.emplace_back(std::make_unique<thing_b>()); 

    for (const auto& t : things) { t.sayHello(); } 
} 

उम्मीद उत्पादन:

hello from A 
hello from B 
+2

यह सवाल का उत्तर कैसे देता है? – Barry

+1

@ बैरी मुझे लगता है कि इस साइट का उद्देश्य प्रश्नों का उत्तर देना है * और * शिक्षित करना। तथ्य यह है कि यदि सुरक्षित रूप से किया जाता है तो पॉलिमॉर्फिज्म वेक्टर की रोकथाम के साथ संगत हो सकता है। यह सुरक्षित रूप से करने के तरीकों में से एक है। जवाब शिक्षा की नस में है। –

2

एक संकलक बहुत कुछ कर सकता है स्थिर विश्लेषण के, और यह पता चल सकता है कि फ़ंक्शन में सूचक arr अप्रत्याशित परिणामों वाले सरणी के रूप में उपयोग किया जाता है।

हालांकि, ऐसा करना धीमा है और स्मृति की बहुत अधिक (अधिक) का उपयोग करता है, और प्रोग्रामर आम तौर पर अधीर होते हैं और जितना संभव हो सके उतने जल्दी संसाधनों को जितना संभव हो सके उतना तेज़ी से पूरा करना चाहते हैं। इसलिए अधिकांश कंपाइलर केवल स्थिर विश्लेषण करते हैं जो अपेक्षाकृत तेज़ और आसान होते हैं, जो समर्पित स्थिर विश्लेषकों को कड़ी मेहनत देते हैं।

+0

तो मुझे लगता है कि आपको लगता है कि 1 का जवाब है) नहीं है। –

+0

@ बेन शायद नहीं। यदि दस्तावेज़ीकरण ऐसी किसी भी चेतावनी का उल्लेख नहीं करता है, तो निश्चित रूप से जानने का एकमात्र तरीका स्रोत प्राप्त होता है (यदि यह उपलब्ध है) और इसे पढ़ें। :) –

+0

मैं वास्तव में संकलन को धीमा करने का तर्क नहीं खरीदता, क्योंकि आमतौर पर चेतावनियां बंद की जा सकती हैं। इसलिए कोई भी जो सुरक्षा के बारे में चिंतित है, उन्हें चालू कर सकता है और संकलन की गति के बारे में चिंतित सभी लोग उन्हें – user463035818

संबंधित मुद्दे