2010-09-03 11 views
15

मैं ओपनडीई के स्रोत के माध्यम से देख रहा था और मैं एक वर्ग पर सरणी अनुक्रमण ऑपरेटर '[]' के कुछ भयंकर सिंटैक्स उपयोग में आया था। यहाँ एक सरल उदाहरण वाक्य रचना दिखाने के लिए है:यह सी ++ वाक्यविन्यास क्या मतलब है और यह क्यों काम करता है?

#include <iostream> 

class Point 
{ 
public: 
    Point() : x(2.8), y(4.2), z(9.5) {} 

    operator const float *() const 
    { 
     return &x; 
    } 

private: 
    float x, y, z; 
}; 

int main() 
{ 
    Point p; 
    std::cout << "x: " << p[0] << '\n' 
       << "y: " << p[1] << '\n' 
       << "z: " << p[2]; 
} 

आउटपुट:

x: 2.8 
y: 4.2 
z: 9.5 

यहाँ क्या हो रहा है? यह वाक्यविन्यास क्यों काम करता है? प्वाइंट क्लास में कोई ओवरलोडेड operator [] नहीं है और यहां यह कोड कहीं भी फ़्लोट करने के लिए स्वचालित रूपांतरण करने का प्रयास कर रहा है।

मैंने कभी इस तरह के उपयोग को कभी नहीं देखा है - यह निश्चित रूप से कम से कम असामान्य और आश्चर्यजनक दिखता है।

धन्यवाद

+4

ध्यान दें कि यह पता लगाने के लिए कि क्या यह 'ऑपरेटर []' या पॉइंटर रूपांतरण फ़ंक्शन का उपयोग कर रहा है, आप यह अजीब परीक्षण कर सकते हैं: यदि '0 [p]' काम करता है, तो यह एक सूचक रूपांतरण का उपयोग कर रहा है। अगर यह काम नहीं करेगा लेकिन यदि 'पी [0]' काम करता है, तो यह 'ऑपरेटर [] 'का उपयोग कर रहा है। –

उत्तर

17

p एक const float* const, जो x के लिए अंक में परोक्ष बदला जा रहा है। तो *px है, *(p+1)y है, और इसी तरह। यह एक बिल्कुल अजीब विचार है (और उलझन में!) इस तरह से ऐसा करने के लिए, बिल्कुल। आमतौर पर एक्स, वाई, और जेड को सरणी में स्टोर करना बेहतर होता है और यदि वे वास्तव में इस तरह से काम करना चाहते हैं तो संपूर्ण सरणी प्राप्त करने के लिए एक फ़ंक्शन है।

+19

उल्लेख नहीं है कि यह पूरी तरह से असुरक्षित है क्योंकि 'x',' y', और 'z' की स्मृति में स्थान अच्छी तरह परिभाषित नहीं है। –

+0

आह ठीक है धन्यवाद। यह कुछ चालाक कोड है ... शायद बहुत चालाक: ओ – greatwolf

+2

@ डी। शॉली: एक अच्छा बिंदु। जबकि एक "उचित" कंपाइलर शायद ऐसा करेगा, मुझे विश्वास नहीं है कि यह लेआउट मानक है कि यह लेआउट मानक है। – rlbond

1

यह आपके सदस्य डेटा को सरणी के रूप में पेश करने का एक तरीका है। आप इसे structs के साथ भी कर सकते हैं। जब आप पठनीयता चाहते हैं तो यह उपयोगी होता है, फिर भी सरल डेटा संरचनाओं पर पुन: प्रयास करने में सक्षम होना चाहते हैं। एक उदाहरण उपयोग इस तरह से एक मैट्रिक्स घोषित करने के लिए होगा:

typedef struct { 
    CGFloat m11,m12,m13,m14; 
    CGFloat m21,m22,m23,m24; 
    CGFloat m31,m32,m33,m34; 
    CGFloat m41,m42,m43,m44; 
} CATransform3D; 

आप आसानी से नाम से प्रत्येक कोशिका संदर्भित कर सकते हैं, फिर भी तुम भी एक सूचक के आसपास पारित कर सकते हैं हर जगह M11 के लिए (और सी एक सरणी के रूप में अपने struct देखेंगे, एम 11 पहला तत्व है), और सभी तत्वों पर पुनरावृत्त।

8

यहां विचार है कि प्वाइंट के सदस्यों को या तो सबस्क्रिप्ट या नाम से एक्सेस देना है।

struct Point { 
    float x, y, z; 

    float &operator[](size_t subscript) { 
     switch(subscript) { 
      case 0: return x; 
      case 1: return y; 
      case 2: return z; 
      default: throw std::range_error("bad subscript"); 
     } 
    } 
}; 

इस तरह संकलक तैरता के बीच गद्दी सम्मिलित करता है, तब यह अभी भी काम करेगा - और किसी को भी, जो कर सकते हैं: आप ऐसा चाहते हैं, हालांकि, आप operator[] कुछ इस तरह अधिक भार बेहतर होगा पढ़ें सी ++ किसी भी समस्या के बिना इसे समझने में सक्षम होना चाहिए।

+1

अच्छा बिंदु। मैं यही सोच रहा हूं। मुझे पता है कि जब मैं स्रोत पर विचार कर रहा था, यह स्पष्ट नहीं था कि कोड क्या कर रहा था। मुझे लगता है कि यह निश्चित रूप से 'कोड के तहत आता है जो अपने स्वयं के लिए बहुत चालाक है'। : 'उचित' कोड के लिए पी – greatwolf

+0

+1 - सुरक्षित, हैंडल त्रुटियां, पठनीय इत्यादि। – JBRWilkinson

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