C ++ में तीर ऑपरेटर सिर्फ * का उपनाम क्यों नहीं है।


18

C ++ में, * ऑपरेटर को अतिभारित किया जा सकता है, जैसे कि एक पुनरावृत्त के साथ, लेकिन तीर (->) (। *) ऑपरेटर उन कक्षाओं के साथ काम नहीं करता है जो * ऑपरेटर को अधिभारित करते हैं। मुझे लगता है कि प्रीप्रोसेसर आसानी से - (* बाएं) के साथ सभी उदाहरणों की जगह ले सकता है। -> अलग होने का एक व्यावहारिक कारण है, या यह कि भाषा / डिजाइनरों की एक ख़ासियत है?

जवाबों:


16

जो नियम केवल foo->barबराबरी के (*foo).barऑपरेटरों के लिए है।

यूनीरी में operator *हमेशा पॉइंटर डेरेफेरेंस शब्दार्थ नहीं होता है। मैं एक पुस्तकालय बना सकता था जिसमें इसका अर्थ होता है मैट्रिक्स ट्रांसपोज़ेशन, शून्य या अधिक पार्सर मिलान, या बहुत कुछ।

यह भाषा को और अधिक परेशान कर देगा यदि ऐसा कुछ भी हो जो operator *एक साथ अचानक से अधिभारित हो जाए, operator ->तो आपके लिए शब्दार्थ के साथ नहीं पूछा जाएगा, जो समझ में नहीं आता है।

operator -> अलग से अधिभार है, इसलिए यदि आप एक चाहते हैं, तो आप न्यूनतम प्रयास के साथ एक को ओवरलोड कर सकते हैं।

यह भी ध्यान दें कि इस तरह के अधिभार में कुछ बल्कि दिलचस्प गुण होंगे, जैसे स्वचालित रूप से operator ->कॉलिंग का पीछा करना जब तक कि चेन में से कोई एक कच्चा पॉइंटर न लौटाए। यह स्मार्ट पॉइंटर्स और अन्य प्रॉक्सी प्रकारों के लिए काफी उपयोगी है।

#include <boost/make_shared.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <iostream>
#include <ostream>

struct Foo
{
    boost::shared_ptr<std::string> operator -> () const
    {
        return boost::make_shared<std::string>("trololo");
    }
};

int main()
{
    Foo foo;
    std::cerr << foo->size() << std::endl;
}

आपका उदाहरण क्या बताता है? क्या आप एक स्ट्रिंग को स्मार्ट पॉइंटर लौटा रहे हैं और किसी भी तरह से आकार दे रहे हैं? मैं उलझन में हूं।
ट्रेवर हिक्की

2
यह मेरे उत्तर के अंतिम पैराग्राफ को दिखाता है कि कैसे ->ऑपरेटर श्रृंखलाओं का उपयोग करते हुए जब तक कि यह किसी चीज को कच्चा सूचक नहीं देता है, इसके सदस्य हैं और इसका सदस्य हैं। यदि ऑपरेटर -> चेन नहीं करता है, तो उदाहरण एक बीमार सूचक के रूप में साझा नहीं किया जाएगा क्योंकि एक साझा सूचक एक कच्चा सूचक नहीं है।
लार्स विकलंड

@LarsViklund: आपके उत्तर में एक समस्या है: आपने कहा था "ऑपरेटर-> ... स्वचालित रूप से चेन ऑपरेटर-> कॉल करता है जब तक कि चेन में से कोई एक कच्चा पॉइंटर न लौटा दे"। यह सही नहीं है - A->Bअधिकतम 1 अतिरिक्त कॉल पर सिंटैक्स चेन का उपयोग करना । सी ++ -> बाइनरी सिंटैक्स वास्तव में क्या करता है, ऑब्जेक्ट के opeartor->सीधे कॉल नहीं करता है - इसके बजाय यह देखता है कि क्या है Aऔर इसकी कच्ची पॉइंटर की जांच करें। यदि यह तब ->इसे निष्क्रिय कर देता है और Bउस पर अमल करता है, अन्यथा यह ऑब्जेक्ट को कॉल करता है operator->, परिणाम को derefs करता है (या तो देशी कच्चे सूचक या किसी अन्य का उपयोग करके operator->और फिर Bपरिणाम पर निष्पादित होता है
Guss

@Guss: मैं आपके दावे के लिए कोई भी अध्याय और कविता नहीं ढूँढ सकता, और न ही इसे किसी कंपाइलर में पुन: पेश कर सकता हूँ। C ++ 11 13.5.6 / 1 इंगित करता है कि यदि एक उपयुक्त अधिभार मौजूद है, x->mतो इसकी व्याख्या की जाएगी (x.operator->())->m। यदि LHS कुछ ऐसा है जिसमें operator->फिर से एक उपयुक्त अधिभार है , तो यह प्रक्रिया तब तक जारी रहती है, जब तक कि (*x).m5.2.5 / 2 का सामान्य प्रभाव न हो।
लार्स विकलंड

8

"सी ++ प्रोग्रामिंग लैंग्वेज" इस तथ्य का वर्णन करती है कि ये ऑपरेटर अलग-अलग हैं ताकि वे हो सकें, लेकिन यह भी कहते हैं:

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

तो ऐसा लगता है कि भाषा डिजाइनरों अलग अधिभार अंक प्रदान की है क्योंकि आप हो सकता है बल्कि यह सोचते हैं कि आप की तुलना में अलग उन्हें ओवरलोड, चाहते हैं हमेशा उन्हें एक ही होना चाहता हूँ।


7

एक सामान्य नियम के रूप में, C ++ को लचीलेपन का पक्ष लेने के लिए डिज़ाइन किया गया है, इसलिए ओवरलोड होते हैं *और ->अलग होते हैं। हालांकि ऐसा करना काफी असामान्य है, अगर आप बुरी तरह से पर्याप्त चाहते हैं तो आप उन ओवरलोड को पूरी तरह से अलग-अलग काम करने के लिए लिख सकते हैं (जैसे, सी ++ के अंदर लागू एक डोमेन विशिष्ट भाषा के लिए समझ में आ सकता है)।

जिसके अनुसार, iterators करना या तो उपयोग समर्थन करते हैं। प्राचीन कार्यान्वयन पर, आपको एक लाइब्रेरी मिल सकती है जिसकी आवश्यकता (*iter).whateverहै iter->whatever, लेकिन यदि हां, तो यह कार्यान्वयन में एक बग है, भाषा की विशेषता नहीं है। सभी मानक कंटेनरों / एल्गोरिदम / पुनरावृत्तियों को लागू करने में शामिल काम की मात्रा को देखते हुए, यह आश्चर्यजनक नहीं है कि कुछ शुरुआती रिलीज़ कुछ अपूर्ण थे, लेकिन वे वास्तव में कभी भी इस तरह से होने का इरादा नहीं थे।


मुझे एहसास नहीं था कि मानक पुस्तकालय के कंटेनरों को लागू किया गया ->, या यह ओवरलोडेबल था।
जैकब वीसब्लाट

3
C ++ 03 24.1 / 1 के लिए आवश्यक है कि कोई भी पुनरावृत्ति जहाँ (*i).mमान्य हो उसे i->mउसी शब्दार्थ के साथ समर्थन करना चाहिए ।
लार्स विकलंड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.