কি vtable
?
ত্রুটি বার্তাটি কী সংশোধন করার চেষ্টা করার আগে সে সম্পর্কে কী বলছে তা জেনে রাখা দরকারী useful আমি একটি উচ্চ স্তরে শুরু করব, তারপরে আরও কিছু বিবরণ নিয়ে কাজ করব। লোকেরা তাদের ভ্যাটেবলগুলি বোঝার জন্য স্বাচ্ছন্দ্য বোধ করলে এইভাবে লোকেরা এগিয়ে যেতে পারে। … এবং এই মুহুর্তে এগিয়ে যাওয়া লোকেরা একসংগে চলে। :) চারপাশে যারা স্টিকি করে তাদের জন্য:
একটি vtable মূলত এর সবচেয়ে সাধারণ বাস্তবায়ন পলিমরফিজম সি ++ এ । যখন ভেটেবল ব্যবহার করা হয়, প্রতিটি পলিমারফিক ক্লাসের প্রোগ্রামের কোথাও একটি ভিটিবেল থাকে; আপনি এটিকে static
ক্লাসের একজন (লুকানো) ডেটা সদস্য হিসাবে ভাবতে পারেন । পলিমারফিক ক্লাসের প্রতিটি অবজেক্ট তার সর্বাধিক উদ্ভূত শ্রেণীর জন্য vtable এর সাথে যুক্ত। এই সমিতিটি পরীক্ষা করে, প্রোগ্রামটি তার বহুবিধ যাদুতে কাজ করতে পারে। গুরুত্বপূর্ণ সতর্কতা : একটি vtable একটি বাস্তবায়ন বিশদ। এটি সি ++ স্ট্যান্ডার্ড দ্বারা বাধ্যতামূলক করা হয় না, যদিও বেশিরভাগ (সমস্ত?) সি ++ সংকলকরা পলিমারফিক আচরণ বাস্তবায়নের জন্য ভিটিবেল ব্যবহার করেন। আমি যে বিবরণগুলি উপস্থাপন করছি তা হয় সাধারণ বা যুক্তিসঙ্গত পন্থা are সংকলকদের এ থেকে বিচ্যুত হওয়ার অনুমতি দেওয়া হয়!
প্রতিটি পলিমারফিক অবজেক্টটির অবজেক্টের সর্বাধিক উদ্ভূত শ্রেণীর (সম্ভবত আরও একাধিক পয়েন্টার, আরও জটিল ক্ষেত্রে) ভিটিবেলের কাছে একটি (লুকানো) পয়েন্টার থাকে। পয়েন্টারটি দেখে প্রোগ্রামটি বলতে পারে যে কোনও বস্তুর "আসল" প্রকারটি কী (নির্মাণের সময় বাদে, তবে আসুন সেই বিশেষ ক্ষেত্রেটি বাদ দেওয়া)। উদাহরণস্বরূপ, যদি কোনও ধরণের A
কোনও অবজেক্টটি ভিটিবেলের দিকে নির্দেশ না করে A
, তবে সেই বস্তুটি আসলে থেকে প্রাপ্ত কোনও কিছুর উপ-অবজেক্ট A
।
"ভিটিবেল" নামটি " ভি ভার্চুয়াল ফাংশন টেবিল " থেকে এসেছে । এটি একটি টেবিল যা পয়েন্টারগুলিকে (ভার্চুয়াল) ফাংশনগুলিতে সঞ্চয় করে। টেবিলটি কীভাবে রাখা হয়েছে তার জন্য একটি সংকলক তার সম্মেলনটি চয়ন করে; একটি সাধারণ পদ্ধতির ভার্চুয়াল ফাংশনগুলি সেগুলি ক্রম সংজ্ঞায়নের মধ্যে ঘোষিত ক্রমের মধ্য দিয়ে যাওয়া। যখন কোনও ভার্চুয়াল ফাংশন বলা হয়, প্রোগ্রামটি বস্তুর পয়েন্টারটিকে একটি ভ্যাটেবলের সাথে অনুসরণ করে, পছন্দসই ফাংশনের সাথে যুক্ত এন্ট্রিতে যায়, তারপরে সঠিক ফাংশনটি আহ্বানের জন্য সঞ্চিত ফাংশন পয়েন্টার ব্যবহার করে। এই কাজটি করার জন্য বিভিন্ন কৌশল রয়েছে তবে আমি এখানে যাব না।
কোথায় / কখন vtable
উত্পন্ন হয়?
কম্পাইলার দ্বারা একটি ভিটিবেল স্বয়ংক্রিয়ভাবে উত্পন্ন হয় (কখনও কখনও "নির্গত" নামে পরিচিত)। একটি সংকলক প্রতিটি অনুবাদ ইউনিটে একটি পলিমারফিক ক্লাস সংজ্ঞা দেখতে পাওয়া একটি ভিটিবেল নির্গত করতে পারে তবে এটি সাধারণত অপ্রয়োজনীয় ওভারকিল হতে পারে। একটি বিকল্প ( জিসিসি দ্বারা ব্যবহৃত হয় , এবং সম্ভবত অন্যরা ব্যবহার করেন) হ'ল একটি একক অনুবাদ ইউনিট বাছাই করা যাতে ভিটিবেল স্থাপন করা যায়, আপনি কীভাবে একটি একক উত্স ফাইলটি বেছে নেবেন যাতে কোনও ক্লাসের স্ট্যাটিক ডেটা সদস্য রাখা যায়। যদি এই নির্বাচন প্রক্রিয়াটি কোনও অনুবাদ ইউনিট বাছাই করতে ব্যর্থ হয়, তবে ভিটিবেল একটি অনির্ধারিত রেফারেন্সে পরিণত হয়। সুতরাং ত্রুটি, যার বার্তা স্বীকৃতভাবে বিশেষভাবে পরিষ্কার নয়।
একইভাবে, যদি বাছাই প্রক্রিয়াটি অনুবাদ ইউনিটটি বেছে নেয়, তবে সেই অবজেক্ট ফাইলটি লিঙ্কারে সরবরাহ করা হয় না, তবে ভিটিবেল একটি অনির্ধারিত রেফারেন্সে পরিণত হয়। দুর্ভাগ্যক্রমে, ত্রুটি বার্তা এই ক্ষেত্রে ক্ষেত্রে বাছাইয়ের প্রক্রিয়া ব্যর্থ হওয়ার ক্ষেত্রে তার চেয়ে কম স্পষ্ট হতে পারে।(উত্তরদাতাদের ধন্যবাদ যারা এই সম্ভাবনার কথা উল্লেখ করেছেন। আমি সম্ভবত তা অন্যথায় ভুলে যেতাম।)
জিসিসি দ্বারা ব্যবহৃত নির্বাচন প্রক্রিয়াটি যদি আমরা প্রতিটি শ্রেণীর জন্য (একক) উত্স ফাইল উত্সর্গকরণের oneতিহ্য দিয়ে শুরু করি যার বাস্তবায়নের জন্য একটির প্রয়োজন হয় তা বোধগম্য হয়। উত্স ফাইলটি সংকলন করার সময় ভিটিবেলটি নির্গত করা ভাল হবে। আসুন যে আমাদের লক্ষ্য। তবে, এই traditionতিহ্যটি না মানলেও বাছাই প্রক্রিয়াটি কাজ করা দরকার। সুতরাং পুরো ক্লাসের বাস্তবায়ন সন্ধানের পরিবর্তে, শ্রেণীর নির্দিষ্ট সদস্যের বাস্তবায়ন সন্ধান করা যাক। যদি traditionতিহ্য অনুসরণ করা হয় - এবং যদি সেই সদস্যটি বাস্তবে বাস্তবায়িত হয় - তবে এটি লক্ষ্য অর্জন করে।
জিসিসি দ্বারা নির্বাচিত সদস্য (এবং অন্যান্য সংকলক দ্বারা সম্ভাব্য) প্রথম অ-ইনলাইন ভার্চুয়াল ফাংশন যা খাঁটি ভার্চুয়াল নয়। আপনি যদি সেই জনতার অংশ হয়ে থাকেন যা অন্যান্য সদস্যের কার্যের আগে নির্মাতা এবং ধ্বংসকারীদের ঘোষণা করে, তবে সেই ডেস্ট্রাক্টর নির্বাচিত হওয়ার ভাল সম্ভাবনা রয়েছে। (আপনি ধ্বংসকারীকে ভার্চুয়াল বানানোর কথা মনে করেন, তাই না?) ব্যতিক্রম আছে; আমি প্রত্যাশা করছিলাম যে ডাস্টস্ট্রাক্টরের জন্য যখন একটি ইনলাইন সংজ্ঞা প্রদান করা হয় এবং যখন ডিফল্ট ডেস্ট্রাক্টরকে অনুরোধ করা হয় (" = default
" ব্যবহার করে ) তখন সর্বাধিক সাধারণ ব্যতিক্রমগুলি হয় ।
বিস্ময়কররা লক্ষ্য করতে পারে যে একটি পলিমারফিক ক্লাসটি তার সমস্ত ভার্চুয়াল ফাংশনের জন্য ইনলাইন সংজ্ঞা প্রদানের অনুমতিপ্রাপ্ত। এর ফলে বাছাই প্রক্রিয়া ব্যর্থ হয় না? এটি পুরানো সংকলকগুলিতে করে। আমি পড়েছি যে সর্বশেষতম সংকলকগণ এই পরিস্থিতিকে সম্বোধন করেছেন, তবে আমি প্রাসঙ্গিক সংস্করণ সংখ্যা জানি না। আমি এটি সন্ধান করার চেষ্টা করতে পারি, তবে এটির চারপাশে কোড করা সহজতর বা সংকলকটির অভিযোগের জন্য অপেক্ষা করা।
সংক্ষেপে, "ভিটেবলের অপরিজ্ঞাত রেফারেন্স" ত্রুটির তিনটি মূল কারণ রয়েছে:
- সদস্য ফাংশনটির সংজ্ঞাটি অনুপস্থিত।
- একটি অবজেক্ট ফাইল লিঙ্ক করা হচ্ছে না।
- সমস্ত ভার্চুয়াল ফাংশনগুলির ইনলাইন সংজ্ঞা রয়েছে।
এই কারণগুলি নিজেরাই ত্রুটি তৈরি করতে অপর্যাপ্ত। বরং ত্রুটি সমাধানের জন্য আপনি এগুলিই সম্বোধন করবেন। আশা করবেন না যে ইচ্ছাকৃতভাবে এই পরিস্থিতিগুলির একটি তৈরি করলে অবশ্যই এই ত্রুটি ঘটবে; অন্যান্য প্রয়োজনীয়তা আছে। আশা করবেন না যে এই পরিস্থিতিগুলি সমাধান করা এই ত্রুটিটি সমাধান করবে।
(ঠিক আছে, এই প্রশ্নটি জিজ্ঞাসা করা হলে 3 নম্বর যথেষ্ট ছিল)
ত্রুটি কিভাবে ঠিক করবেন?
এগিয়ে এড়ানো মানুষ ফিরে স্বাগতম! :)
- আপনার শ্রেণির সংজ্ঞা দেখুন। প্রথম নন-ইনলাইন ভার্চুয়াল ফাংশন সন্ধান করুন যা খাঁটি ভার্চুয়াল নয় ("
= 0
" নয়) এবং যার সংজ্ঞা আপনি সরবরাহ করেন (" = default
" নয়)।
- যদি এরকম কোনও কার্যকারিতা না থাকে তবে আপনার শ্রেণিটি সংশোধন করার চেষ্টা করুন যাতে একটি রয়েছে। (ত্রুটি সম্ভবত সমাধান হয়েছে))
- একটি সতর্কতার জন্য ফিলিপ থমাসের উত্তরও দেখুন ।
- এই ফাংশনটির জন্য সংজ্ঞাটি সন্ধান করুন। যদি এটি অনুপস্থিত থাকে তবে এটি যুক্ত করুন! (ত্রুটি সম্ভবত সমাধান হয়েছে))
- আপনার লিঙ্ক কমান্ড পরীক্ষা করুন। যদি এটি ফাংশনের সংজ্ঞা সহ অবজেক্ট ফাইলটির উল্লেখ না করে তবে এটি ঠিক করুন! (ত্রুটি সম্ভবত সমাধান হয়েছে))
- ত্রুটি সমাধান না হওয়া অবধি প্রতিটি ভার্চুয়াল ফাংশনের জন্য 2 এবং 3 পদক্ষেপ পুনরাবৃত্তি করুন, তারপরে প্রতিটি অ-ভার্চুয়াল ফাংশনের জন্য। আপনি যদি এখনও আটকে থাকেন তবে প্রতিটি স্থির ডেটা সদস্যের জন্য পুনরাবৃত্তি করুন।
উদাহরণ
কী করা উচিত তার বিবরণগুলি পৃথক হতে পারে এবং কখনও কখনও পৃথক প্রশ্নে বিভক্ত হয় ( যেমন একটি অপরিজ্ঞাত রেফারেন্স / অমীমাংসিত বাহ্যিক প্রতীক ত্রুটি কী এবং আমি কীভাবে এটি ঠিক করব? )। যদিও আমি একটি নির্দিষ্ট ক্ষেত্রে কী করব তার একটি উদাহরণ প্রদান করব যা নতুন প্রোগ্রামারগুলিকে বিভ্রান্ত করতে পারে।
পদক্ষেপ 1 আপনার শ্রেণিটি সংশোধন করার উল্লেখ করেছে যাতে এটিতে একটি নির্দিষ্ট ধরণের ফাংশন থাকে। যদি সেই ফাংশনটির বিবরণটি আপনার মাথার উপরে চলে যায় তবে আপনি যে পরিস্থিতিতে আমি সম্বোধন করতে চান তা আপনি হতে পারেন। মনে রাখবেন যে লক্ষ্যটি অর্জনের এটি একটি উপায়; এটি একমাত্র উপায় নয় এবং সহজেই আপনার নির্দিষ্ট পরিস্থিতিতে আরও ভাল উপায় থাকতে পারে। আসুন আপনার ক্লাস কল A
। আপনার ডেস্ট্রাক্টর কি হিসাবে ঘোষিত হয়েছে (আপনার শ্রেণির সংজ্ঞায়)
virtual ~A() = default;
অথবা
virtual ~A() {}
? যদি তা হয় তবে দুটি পদক্ষেপ আপনার ডিস্ট্রাক্টরকে আমাদের ফাংশনটির ধরণে পরিবর্তন করবে। প্রথমে সেই লাইনটি পরিবর্তন করুন
virtual ~A();
দ্বিতীয়ত, নিম্নলিখিত উত্সটি এমন একটি উত্স ফাইলে রাখুন যা আপনার প্রকল্পের অংশ (সাধারণত শ্রেণীর প্রয়োগের ফাইলটি যদি আপনার থাকে তবে):
A::~A() {}
এটি আপনার (ভার্চুয়াল) ডেস্ট্রাক্টরকে নন-ইনলাইন করে এবং সংকলক দ্বারা তৈরি করা হয় না। (আপনার কোড বিন্যাস শৈলীর সাথে আরও ভাল মেলে জিনিসগুলি সংশোধন করতে দ্বিধা বোধ করুন, যেমন ফাংশন সংজ্ঞাতে শিরোনাম মন্তব্য যুক্ত করুন))