কেন সি ++ এ থাকা তীর অপারেটর কেবল * এর একটি উপন্যাস নয়?


18

সি ++ এ, * অপারেটর ওভারলোড করা যেতে পারে, যেমন একটি পুনরুক্তি দিয়ে, তবে তীর (->) (। *) অপারেটর যে ক্লাসগুলি * অপারেটরকে ওভারলোড করে তার সাথে কাজ করে না। আমি কল্পনা করি যে প্রিপ্রসেসর সহজেই -> এর সমস্ত দৃষ্টান্ত (* বাম) দিয়ে ডানদিকে প্রতিস্থাপন করতে পারে এবং এটি পুনরাবৃত্তিকে কার্যকর করতে আরও সুন্দর করে তুলবে। -> আলাদা হওয়ার কোনও ব্যবহারিক কারণ আছে, বা এটি কি ভাষা / ডিজাইনারদের এক বিশেষত্ব?

উত্তর:


16

যে বিধিটি কেবলমাত্র বিল্টিন অপারেটরদের জন্য foo->barসমান (*foo).bar

Unary operator *সবসময় পয়েন্টার dereferences শব্দার্থবিজ্ঞান থাকে না। আমি একটি লাইব্রেরি তৈরি করতে পারলাম যার অর্থ ম্যাট্রিক্স স্থানান্তর, শূন্য বা আরও পার্সার মিল, বা আরও অনেক কিছু।

ভাষাটি আরও উদ্বেগজনক করে তুলবে যদি অযথা ওভারলোডগুলি এমন কিছু 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
এটি আমার উত্তরের শেষ অনুচ্ছেদে চিত্রিত করে যে কীভাবে ->অপারেটর চেইন ব্যবহার করা হয় যতক্ষণ না এটি কোনও কিছুর কোনও কাঁচা পয়েন্টার না পাওয়া পর্যন্ত, এর কোনও সদস্যকে অবলম্বন করে এবং অ্যাক্সেস করে। যদি অপারেটর -> চেইন না করে থাকে তবে উদাহরণটি ভাগ করে নেওয়া হবে কারণ একটি ভাগ করা_প্ট্রার কোনও কাঁচা পয়েন্টার নয়।
Lars ভিক্লুন্ড

@ লার্সভিক্লুন্ড: আপনার উত্তরে একটি সমস্যা রয়েছে: আপনি বলেছিলেন "অপারেটর-> ... স্বয়ংক্রিয়ভাবে চেইন অপারেটর-> কল করুন যতক্ষণ না শৃঙ্খলে থাকা কোনও ব্যক্তি কোনও কাঁচা পয়েন্টার না ফেরায়"। এটি সঠিক নয় - A->Bসর্বাধিক 1 টি অতিরিক্ত কল সিটেক্স চেইন ব্যবহার করে । সি ++ -> বাইনারি সিনট্যাক্সটি আসলে কী করে তা বস্তুর opeartor->সরাসরি কল করা হয় না - পরিবর্তে এটির ধরণটি দেখে এবং এটি Aকোনও কাঁচা পয়েন্টার কিনা তা পরীক্ষা করে। যদি এটির পরে ->এটি ডিফ করা হয় এবং এটি কার্যকর করা Bহয়, অন্যথায় এটি বস্তুর ডাকে operator->, ফলাফলকে derefs করে (হয় দেশীয় কাঁচা পয়েন্টার বা অন্য কোনওটি ব্যবহার করে operator->এবং তারপরে Bফলাফলটি কার্যকর করে
Guss

@ গুস: আপনার দাবির জন্য আমি কোনও অধ্যায় এবং শ্লোকটি খুঁজে পাচ্ছি না এবং সংকলকটিতে এটি পুনরুত্পাদন করতে পারি না। সি ++ 11 13.5.6 / 1 ইঙ্গিত দেয় যে উপযুক্ত ওভারলোড যদি বিদ্যমান থাকে তবে x->mতা ব্যাখ্যা করা হবে (x.operator->())->m। যদি এলএইচএস আবার এমন একটি উপযুক্ত ওভারলোড থাকে তবে operator->এই প্রক্রিয়াটি কেবল (*x).m5.2.5 / 2 এর স্বাভাবিক প্রভাব না হওয়া পর্যন্ত পুনরাবৃত্তি করে ।
লার্স ভিক্লুন্ড

8

"সি ++ প্রোগ্রামিং ল্যাঙ্গুয়েজ" এই অপারেটরগুলি যাতে আলাদা হতে পারে তার চেয়ে পৃথক, তবে আরও বলেছেন:

আপনি যদি এই অপারেটরের একটিরও বেশি সরবরাহ করেন তবে সমতা প্রদান করা বুদ্ধিমানের কাজ যেমন হতে পারে তা নিশ্চিত করা ++xএবং কিছু শ্রেণীর সাধারণ ভেরিয়েবলের x+=1মতো একই প্রভাব যদি ++, + =, =, এবং + সরবরাহ করা হয়।x=x+1x

সুতরাং দেখে মনে হয় যে ভাষা ডিজাইনাররা পৃথক ওভারলোড পয়েন্ট সরবরাহ করেছিল কারণ আপনি সর্বদা সেগুলি একই হতে চান এমনটি ধরে না রেখে আপনি এগুলি আলাদাভাবে ওভারলোড করতে চান ।


7

একটি সাধারণ নিয়ম অনুযায়ী, সি ++ পক্ষে নমনীয়তা করার জন্য ডিজাইন করা হয়, যাতে এর overloads *এবং ->আলাদা হয়। যদিও এটি করা মোটামুটি অস্বাভাবিক, আপনি যদি খুব খারাপভাবে করতে চান তবে আপনি এই ওভারলোডগুলি সম্পূর্ণ ভিন্ন জিনিস করতে লিখতে পারেন (উদাহরণস্বরূপ, সি ++ এর অভ্যন্তরে প্রয়োগ করা একটি ডোমেন নির্দিষ্ট ভাষার জন্য অর্থ হতে পারে)।

তাই বলা হয়, iterators না পারেন ব্যবহার সমর্থন করে। প্রাচীন বাস্তবায়নে, আপনি সম্ভবত একটি লাইব্রেরি খুঁজে পেতে পারেন যা (*iter).whateverপরিবর্তে প্রয়োজন হয় iter->whatever, তবে যদি তা হয় তবে এটি বাস্তবায়নের ক্ষেত্রে একটি বাগ, ভাষার কোনও বৈশিষ্ট্য নয়। সমস্ত স্ট্যান্ডার্ড পাত্রে / অ্যালগরিদম / পুনরুক্তি প্রয়োগের সাথে জড়িত কাজের পরিমাণ দেওয়া, এটি আশ্চর্যজনক কিছু নয় যে কিছু প্রাথমিক প্রকাশ কিছুটা অসম্পূর্ণ ছিল, তবে সেগুলি সত্যই কখনও সেভাবে হওয়ার ইচ্ছা ছিল না।


আমি প্রয়োগকৃত স্ট্যান্ডার্ড লাইব্রেরি পাত্রে বুঝতে পারি নি -> অথবা এটি ওভারলোডযোগ্য।
জ্যাকব ওয়েজব্লাত

3
সি ++ 03 24.1 / 1 এর জন্য আবশ্যক যে কোনও পুনরাবৃত্তি (*i).mবৈধ যেখানে i->mএকই শব্দার্থবিজ্ঞানের সাথে সমর্থন করতে হবে ।
লার্স ভিক্লুন্ড
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.