আমি শুনেছি static_cast
ফাংশনটি সি-স্টাইল বা সাধারণ ফাংশন-স্টাইলের castালাইয়ের পক্ষে পছন্দ করা উচিত। এটা কি সত্য? কেন?
আমি শুনেছি static_cast
ফাংশনটি সি-স্টাইল বা সাধারণ ফাংশন-স্টাইলের castালাইয়ের পক্ষে পছন্দ করা উচিত। এটা কি সত্য? কেন?
উত্তর:
প্রধান কারণ যে ক্লাসিক সি কাস্ট আমরা কি কল মধ্যে পার্থক্য করি না হয় static_cast<>()
, reinterpret_cast<>()
, const_cast<>()
, এবংdynamic_cast<>()
। এই চারটি জিনিস সম্পূর্ণ আলাদা।
এ static_cast<>()
সাধারণত নিরাপদ থাকে। ভাষাতে একটি বৈধ রূপান্তর আছে, বা একটি উপযুক্ত নির্মাতা যা এটি সম্ভব করে। আপনি যখন উত্তরাধিকার সূত্রে প্রাপ্ত ক্লাসে ফেলে দেন কেবল তখনই কিছুটা ঝুঁকিপূর্ণ হয়; আপনাকে অবশ্যই নিশ্চিত করতে হবে যে বস্তুটি আসলে যে বংশধর আপনি দাবি করেছেন এটি ভাষার বাইরে, (বস্তুর পতাকার মতো)। একজনdynamic_cast<>()
যতদিন ফলাফলের পরীক্ষা করা হয় (পয়েন্টার) অথবা একটি সম্ভাব্য ব্যতিক্রম অ্যাকাউন্ট (রেফারেন্স) বিবেচনায় নেয়া হয় নিরাপদ।
অন্যদিকে ক reinterpret_cast<>()
(বা ক const_cast<>()
) সর্বদা বিপজ্জনক। আপনি সংকলককে বলেছেন: "আমার উপর আস্থা রাখুন: আমি জানি এটি কোনও foo
রূপের মতো দেখাচ্ছে না (এটি দেখে মনে হচ্ছে এটি পরিবর্তনীয় নয়), তবে এটি"।
প্রথম সমস্যাটি হ'ল কোডের বৃহত এবং বিচ্ছুরিত অংশগুলি না দেখে এবং সমস্ত নিয়ম না জেনে কোনও সি-স্টাইলের কাস্টে কোনটি ঘটবে তা বলা প্রায় অসম্ভব।
আসুন এইগুলি ধরে নেওয়া যাক:
class CDerivedClass : public CMyBase {...};
class CMyOtherStuff {...} ;
CMyBase *pSomething; // filled somewhere
এখন, এই দুটি একইভাবে সংকলিত হয়েছে:
CDerivedClass *pMyObject;
pMyObject = static_cast<CDerivedClass*>(pSomething); // Safe; as long as we checked
pMyObject = (CDerivedClass*)(pSomething); // Same as static_cast<>
// Safe; as long as we checked
// but harder to read
যাইহোক, আসুন এটি প্রায় অভিন্ন কোডটি দেখুন:
CMyOtherStuff *pOther;
pOther = static_cast<CMyOtherStuff*>(pSomething); // Compiler error: Can't convert
pOther = (CMyOtherStuff*)(pSomething); // No compiler error.
// Same as reinterpret_cast<>
// and it's wrong!!!
যেমন আপনি দেখতে পাচ্ছেন, জড়িত সমস্ত শ্রেণীর সম্পর্কে অনেক কিছু না জেনে দুটি পরিস্থিতির মধ্যে পার্থক্য করার সহজ উপায় নেই।
দ্বিতীয় সমস্যাটি হ'ল সি-স্টাইলের বর্ণগুলি সনাক্ত করা খুব শক্ত hard জটিল অভিব্যক্তিগুলিতে সি-স্টাইলের কাস্টগুলি দেখতে খুব কঠিন হতে পারে। সম্পূর্ণ স্বয়ংক্রিয় সি ++ কম্পাইলার ফ্রন্ট-এন্ড ছাড়াই একটি স্বয়ংক্রিয় সরঞ্জাম লিখতে সি-স্টাইলের ক্যাসেটগুলি (উদাহরণস্বরূপ একটি অনুসন্ধান সরঞ্জাম) সনাক্ত করা দরকার যা কার্যত অসম্ভব। অন্যদিকে, "স্ট্যাটিক_কাস্ট <" বা "পুনরায় ব্যাখ্যা_কাস্ট <" অনুসন্ধান করা সহজ।
pOther = reinterpret_cast<CMyOtherStuff*>(pSomething);
// No compiler error.
// but the presence of a reinterpret_cast<> is
// like a Siren with Red Flashing Lights in your code.
// The mere typing of it should cause you to feel VERY uncomfortable.
এর অর্থ এই যে, কেবল সি-স্টাইলের কাস্টগুলিই আরও বিপজ্জনক নয়, এগুলি সঠিক কিনা তা নিশ্চিত করার জন্য তাদের সমস্ত খুঁজে পাওয়া অনেক বেশি শক্ত।
static_cast
উত্তরাধিকারের শ্রেণিবদ্ধতা কাস্ট করার জন্য আপনার ব্যবহার করা উচিত নয় , বরং dynamic_cast
। এটি নাল পয়েন্টার বা বৈধ পয়েন্টারটি ফেরত দেবে।
static_cast
সেই পরিস্থিতিতে ব্যবহারের দিকে সাবধান করেছিলাম । dynamic_cast
নিরাপদ হতে পারে তবে এটি সর্বদা সেরা বিকল্প নয়। কখনও কখনও আপনি জানেন যে একটি পয়েন্টার একটি প্রদত্ত সাব টাইপ নির্দেশ করে, সংকলকটির মাধ্যমে অস্বচ্ছ এবং static_cast
দ্রুততর হয়। কমপক্ষে কিছু পরিবেশে, dynamic_cast
alচ্ছিক সংকলক সমর্থন এবং রানটাইম ব্যয়ের প্রয়োজন (আরটিটিআই সক্ষম করে) এবং আপনি নিজে যা করতে পারেন তার জন্য কেবল কয়েকটি চেকের জন্য এটি সক্ষম করতে চাইবেন না। সি ++ এর আরটিটিআই হ'ল সমস্যার একমাত্র সম্ভাব্য সমাধান।
static_cast
। এর সমতুল্য reinterpret_cast
হ'ল *(destination_type *)&
অর্থের অর্থের ঠিকানা গ্রহণ করা, সেই ঠিকানাটিকে অন্য কোনও ধরণের পয়েন্টারে ingালাই করা, এবং তারপরে নির্ধারণ করা। চরিত্র ধরনের নির্দিষ্ট struct হয় ধরনের ক্ষেত্রে, যার জন্য সি এই কনস্ট্রাক্ট আচরণ সংজ্ঞায়িত ছাড়া, এটা সাধারণত সি অনির্ধারিত আচরণ ফলাফল
int
(এবং int
একা) জন্য কেন ব্যবহার করুন usestatic_cast<int>
বনামকে (int)
একমাত্র উপকার হিসাবে বেনিফিট হিসাবে বর্গ ভেরিয়েবল এবং পয়েন্টারগুলির সাথে মনে হয়। আপনি এই সম্পর্কে বিস্তারিত জানাতে অনুরোধ।
int
dynamic_cast
প্রয়োগ হয় না, তবে অন্যান্য সমস্ত কারণ দাঁড়িয়েছে। উদাহরণস্বরূপ: ধরা যাক v
একটি ফাংশন প্যারামিটার হিসাবে ঘোষিত float
, তারপর (int)v
হয় static_cast<int>(v)
। কিন্তু যদি আপনাকে প্যারামিটার পরিবর্তন float*
, (int)v
শান্তভাবে হয়ে reinterpret_cast<int>(v)
যখন static_cast<int>(v)
অবৈধ এবং সঠিকভাবে কম্পাইলার হাতে ক্যাচ হয়।
একটি বাস্তববাদী টিপ: আপনি যদি প্রকল্পটি সজ্জিত করার পরিকল্পনা করেন তবে আপনি আপনার উত্স কোডের স্ট্যাটিক_কাস্ট কীওয়ার্ডটির জন্য সহজেই অনুসন্ধান করতে পারেন।
int
প্যারামিটার সহ একটি কার্য ঘোষণা decla
সংক্ষেপে :
static_cast<>()
আপনাকে একটি সংকলন সময় চেক করার ক্ষমতা দেয়, সি স্টাইলের কাস্ট দেয় না।static_cast<>()
সি ++ উত্স কোডের ভিতরে যে কোনও জায়গায় সহজেই স্পট করা যায়; বিপরীতে, সি_স্টাইল কাস্ট স্পট করা শক্ত।- সি ++ কাস্ট ব্যবহার করে ইন্টেন্টেশনগুলি আরও ভালভাবে জানানো হয়।
আরও ব্যাখ্যা :
স্ট্যাটিক কাস্ট সামঞ্জস্যপূর্ণ ধরণের মধ্যে রূপান্তর সম্পাদন করে । এটি সি-স্টাইলের castালাইয়ের মতো, তবে এটি আরও বাধাজনক। উদাহরণস্বরূপ, সি-স্টাইলের castালাই একটি পূর্ণসংখ্যার পয়েন্টারটিকে একটি চরকে নির্দেশ করতে দেয়।
char c = 10; // 1 byte int *p = (int*)&c; // 4 bytes
যেহেতু এটির ফলাফল 4-বাইট পয়েন্টার বরাদ্দ মেমরির 1 বাইট প্রতি নির্দেশ করে, তাই এই পয়েন্টারে লেখাটি রান-টাইম ত্রুটির কারণ হতে পারে বা কিছু সংলগ্ন স্মৃতিতে ওভাররাইট করে।
*p = 5; // run-time error: stack corruption
সি-স্টাইলের কাস্টের বিপরীতে, স্ট্যাটিক castালাই সংকলকটিকে পয়েন্টার এবং পয়েন্টি ডেটা প্রকারের সাথে সামঞ্জস্যপূর্ণ তা পরীক্ষা করতে দেয় যা প্রোগ্রামারকে সংকলনের সময় এই ভুল পয়েন্টার অ্যাসাইনমেন্টটি ধরতে দেয়।
int *q = static_cast<int*>(&c); // compile-time error
আরও পড়ুন:
স্ট্যাটিক_কাস্ট <> এবং সি স্টাইল কাস্টিং
এবং নিয়মিত কাস্ট বনাম স্ট্যাটিক_কাস্ট বনাম গতিশীল_কাস্টের মধ্যে পার্থক্য কী?
static_cast<>()
চেয়ে বেশি পাঠযোগ্য disag মানে, কখনও কখনও এটি হয় তবে বেশিরভাগ সময় - বিশেষত মৌলিক পূর্ণসংখ্যার ধরণের ক্ষেত্রে - এটি কেবল ভয়াবহ এবং অহেতুক ভার্জোজ। উদাহরণস্বরূপ: এটি এমন একটি ফাংশন যা 32-বিট শব্দের বাইটগুলিকে অদলবদল করে। static_cast<uint##>()
কাস্ট ব্যবহার করে পড়া প্রায় অসম্ভব , তবে (uint##)
ক্যাসেট ব্যবহার করে বোঝা বেশ সহজ । কোডের ছবি: imgur.com/NoHbGve
always
। (তবে বেশিরভাগ সময় হ্যাঁ) এমন কিছু ঘটনা রয়েছে যা সি স্টাইলের castালাই আরও বেশি পঠনযোগ্য। সি স্টাইলের ingালাই এখনও একটি কারণ যা এখনও লাইভ এবং সি ++ ইমোতে লাথি মারছে ts :) যাইহোক, এটি একটি খুব দুর্দান্ত উদাহরণ ছিল
(uint32_t)(uint8_t)
সর্বনিম্ন ছাড়াও বাইটগুলি পুনরায় সেট করার জন্য । এর জন্য বিটওয়াইজ এবং ( 0xFF &
) রয়েছে। কাস্টের ব্যবহারের উদ্দেশ্যটি হস্তক্ষেপ করছে।
প্রশ্নটি কেবল মজাদার স্ট্যাটিক_কাস্ট বা সি স্টাইলের কাস্টিং ব্যবহারের চেয়ে বড় কারণ সি স্টাইলের ক্যাসেট ব্যবহার করার সময় বিভিন্ন জিনিস ঘটে থাকে। সি ++ castালাই অপারেটরগুলির উদ্দেশ্য এই ক্রিয়াকলাপগুলি আরও স্পষ্ট করে তোলা।
পৃষ্ঠের উপর স্থির_কাস্ট এবং সি স্টাইলের কাস্টগুলি একই জিনিসটিতে উপস্থিত হয়, উদাহরণস্বরূপ, যখন একটি মানকে অন্যটিতে মূল্য দেওয়া হয়:
int i;
double d = (double)i; //C-style cast
double d2 = static_cast<double>( i ); //C++ cast
এই দুটিই পূর্ণসংখ্যার মানকে দ্বিগুণ করে। তবে পয়েন্টারগুলির সাথে কাজ করার সময় জিনিসগুলি আরও জটিল হয় get কিছু উদাহরণ:
class A {};
class B : public A {};
A* a = new B;
B* b = (B*)a; //(1) what is this supposed to do?
char* c = (char*)new int( 5 ); //(2) that weird?
char* c1 = static_cast<char*>( new int( 5 ) ); //(3) compile time error
এই উদাহরণে (1) সম্ভবত ঠিক আছে কারণ এ দ্বারা নির্দেশিত বস্তুটি আসলেই বি এর একটি উদাহরণ, তবে আপনি যদি কোডের সেই বিন্দুতে না জানেন তবে আসলে কী বোঝায়? (২) হতে পারে পুরোপুরি আইনী (আপনি কেবলমাত্র পূর্ণসংখ্যার এক বাইটটি দেখতে চান), তবে এটি ভুলও হতে পারে যে ক্ষেত্রে কোনও ত্রুটি সুন্দর হবে (৩)। সি ++ ingালাই অপারেটরগুলি যখন সম্ভব হবে তখন সংকলন-সময় বা রান-টাইম ত্রুটিগুলি সরবরাহ করে কোডগুলিতে এই সমস্যাগুলি প্রকাশ করার উদ্দেশ্যে।
সুতরাং, কঠোর "মান কাস্টিং" এর জন্য আপনি স্ট্যাটিক_কাস্ট ব্যবহার করতে পারেন। আপনি যদি পয়েন্টারগুলির রান-টাইম পলিমারফিক কাস্টিং চান তবে ডায়নামিক_কাস্ট ব্যবহার করুন। আপনি যদি প্রকারের সম্পর্কে সত্যই ভুলে যেতে চান তবে আপনি পুনরায় ব্যাখ্যা_কাস্ট ব্যবহার করতে পারেন। এবং কনস্ট কনস্টাস্ট উইন্ডোটি বাইরে ফেলে দিতে কনস্টকাস্ট রয়েছে।
তারা কেবল কোডটি আরও স্পষ্ট করে তোলে যাতে দেখে মনে হয় আপনি কী করছেন।
static_cast
এর অর্থ হ'ল আপনি দুর্ঘটনাক্রমে const_cast
বা পারবেন না reinterpret_cast
, যা একটি ভাল জিনিস।
দেখুন কার্যকরী সি ++ ভূমিকা
আপনি কত প্রকার সুরক্ষা চাপাতে চান তা এটি।
আপনি যখন লিখবেন (bar) foo
(যা সমান)reinterpret_cast<bar> foo
আপনি কোনও ধরণের রূপান্তরকারী অপারেটর সরবরাহ না থাকেন ) আপনি সংকলককে টাইপ সুরক্ষা উপেক্ষা করার জন্য বলছেন, এবং যেমন বলা হয়েছে ঠিক তেমন করুন।
আপনি যখন লিখবেন তখন static_cast<bar> foo
কমপায়ারটিকে কমপক্ষে রূপান্তর কোডটি প্রবেশ করানোর জন্য টাইপ রূপান্তরটি বোঝায় এবং অবিচ্ছেদ্য ধরণের জন্য, তা পরীক্ষা করতে জিজ্ঞাসা করছেন।
সম্পাদনা 2014-02-26
আমি এই উত্তরটি 5 বছরেরও বেশি আগে লিখেছি, এবং আমি এটি ভুল পেয়েছি। (মন্তব্য দেখুন।) কিন্তু এটি এখনও upvotes পায়!
static_cast<bar>(foo)
বন্ধনী সহ। একই জন্য reinterpret_cast<bar>(foo)
।
সি স্টাইল কাস্টগুলি কোডের একটি ব্লকে মিস করা সহজ miss সি ++ স্টাইলের কাস্টগুলি কেবল আরও ভাল অনুশীলন নয়; তারা নমনীয়তা অনেক বড় ডিগ্রী অফার।
পুনরায় ব্যাখ্যা_কাস্ট পয়েন্টার ধরণের রূপান্তরগুলিতে অবিচ্ছেদ্য অনুমতি দেয়, তবে অপব্যবহার করা গেলে এটি অনিরাপদ হতে পারে।
স্ট্যাটিক_কাস্ট সংখ্যাসূচক প্রকারের জন্য যেমন রূপান্তরিত হয় যেমন এনামস থেকে অন্তর্নির্মিত থেকে ইনটস বা ইনটস ফ্লোটে বা যে কোনও ডেটা টাইপের বিষয়ে আপনি যেমন আত্মবিশ্বাসী, তেমন রূপান্তর সরবরাহ করে। এটি কোনও রান টাইম চেক করে না।
অন্যদিকে ডায়নামিক_কাস্ট কোনও অস্পষ্ট কাজ বা রূপান্তরকে চিহ্নিত করে এই চেকগুলি সম্পাদন করবে। এটি কেবল পয়েন্টার এবং রেফারেন্সে কাজ করে এবং একটি ওভারহেড অন্তর্ভুক্ত করে।
আরও কয়েকজন রয়েছেন তবে এগুলি হ'ল মূল আপনি যা করতে পারেন।
স্ট্যাটিক_কাস্ট, ক্লাসে পয়েন্টার হেরফের বাদে ক্লাসে স্পষ্টভাবে সংজ্ঞায়িত রূপান্তর সম্পাদন করতে, পাশাপাশি মৌলিক ধরণের মধ্যে স্ট্যান্ডার্ড রূপান্তর সম্পাদন করতেও ব্যবহার করা যেতে পারে:
double d = 3.14159265;
int i = static_cast<int>(d);
static_cast<int>(d)
যখন কেউ লিখবেন (int)d
? (আমার অর্থ মৌলিক ধরণের ক্ষেত্রে, পয়েন্টারগুলির মতো নয়))
(int)d
সময় কেউ কেন লিখবে int{d}
? কনস্ট্রাক্টর, বা ফাংশন-এর মতো যদি আপনার থাকে তবে ()
বাক্য বাক্সগুলিতে জটিল এক্সপ্রেশনগুলিতে প্যারেন্টেসিসের একটি নাইটমারিশ গোলকধাঁধার মধ্যে রূপান্তর করতে সিনট্যাক্স প্রায় তত দ্রুত নয়। এই ক্ষেত্রে, এটি int i{d}
পরিবর্তে চাই int i = (int)d
। আরও ভাল আইএমও এটি বলেছিল, যখন আমার কেবলমাত্র একটি অভিব্যক্তিতে একটি অস্থায়ী প্রয়োজন হয়, আমি static_cast
কখনও নির্মাণকারী কাস্ট ব্যবহার করি না এবং ব্যবহার করি না, আমি ভাবি না। আমি কেবল (C)casts
তাত্ক্ষণিকভাবে ডিবাগ cout
গুলি লিখতে গিয়ে ব্যবহার করি ...