আপনি স্ট্যান্ড :: ভেক্টর থেকে উত্তরাধিকারী হবে না


189

ঠিক আছে, স্বীকার করা সত্যই কঠিন, তবে উত্তরাধিকারী হওয়ার জন্য আমার এই মুহুর্তে প্রবল প্রলোভন রয়েছে std::vector

আমার ভেক্টরের জন্য প্রায় 10 টি কাস্টমাইজড অ্যালগরিদম প্রয়োজন এবং আমি তাদের সরাসরি ভেক্টরের সদস্য হতে চাই। তবে স্বাভাবিকভাবেই আমি বাকী std::vectorইন্টারফেসটিও রাখতে চাই। ঠিক আছে, আইন মেনে চলা নাগরিক হিসাবে আমার প্রথম ধারণাটি ছিল ক্লাসে std::vectorসদস্য হওয়া MyVector। তবে তখন আমাকে স্ট্যান্ড :: ভেক্টরের ইন্টারফেসের ম্যানুয়ালি পুনঃপ্রবিষ্ট করতে হবে। খুব বেশি টাইপ করতে হবে। এরপরে, আমি ব্যক্তিগত উত্তরাধিকার সম্পর্কে ভেবেছিলাম, যাতে পদ্ধতিগুলি পুনর্নির্মাণের পরিবর্তে আমি using std::vector::memberপাবলিক বিভাগে একগুচ্ছ লিখতে পারি । এটি আসলে খুব ক্লান্তিকর।

এবং আমি এখানে আছি, আমি সত্যিই ভাবি যে আমি কেবল প্রকাশ্যভাবে এর উত্তরাধিকারী হতে পারি std::vector, তবে ডকুমেন্টেশনে একটি সতর্কতা প্রদান করেছি যে এই শ্রেণিটি বহিরাগতভাবে ব্যবহার করা উচিত নয়। আমি মনে করি বেশিরভাগ বিকাশকারীরা এটি বুঝতে যথেষ্ট পারদর্শী যে এটি যেহেতু বহিরাগতভাবে ব্যবহার করা উচিত নয়।

আমার সিদ্ধান্তটি কি একেবারেই আপত্তিজনক নয়? যদি তাই হয় তবে কেন? আপনি কি এমন বিকল্প সরবরাহ করতে পারেন যার অতিরিক্ত সদস্যরা আসলে সদস্য থাকবেন তবে ভেক্টরের ইন্টারফেসের সমস্তটি পুনরায় টাইপ করা জড়িত না? আমি এটি সন্দেহ করি, তবে আপনি যদি পারেন তবে আমি কেবল খুশি হব।

এছাড়াও, কিছু ইডিয়ট এমন কিছু লিখতে পারে apart

std::vector<int>* p  = new MyVector

মাইভেক্টর ব্যবহারে অন্য কোন বাস্তব বিপদ আছে? বাস্তববাদী বলার মাধ্যমে আমি এমন জিনিসগুলিকে বাতিল করে দিই যেমন কোনও ফাংশনটি কল্পনা করে যা ভেক্টরের কাছে পয়েন্টার নেয় ...

ঠিক আছে, আমি আমার কেস বলেছি। আমি পাপ করেছি. এখন আমাকে ক্ষমা করা বা না করা এখন আপনার উপর নির্ভর করে :)


9
সুতরাং, আপনি মূলত জিজ্ঞাসা করছেন যে আপনি ধারকটির ইন্টারফেসটি পুনরায় প্রয়োগ করতে খুব অলস হয়ে আছেন তার ভিত্তিতে কোনও সাধারণ নিয়ম লঙ্ঘন করা ঠিক আছে কিনা? তাহলে না, তা নয়। দেখুন, আপনি যদি এই তেতো বড়িটি গ্রাস করেন এবং এটি সঠিকভাবে করেন তবে আপনার উভয় বিশ্বের সেরা থাকতে পারে। লোকটি হবেন না শক্ত কোড লিখুন।
জিম ব্রিসোম

7
আপনি / সদস্যহীন ফাংশনগুলির সাথে আপনার প্রয়োজনীয় কার্যকারিতাটি কেন যুক্ত করতে চান না? আমার কাছে, এই দৃশ্যে সবচেয়ে নিরাপদ কাজ হবে।
সিমোন

11
@ জিম: std::vectorএর ইন্টারফেসটি বেশ বিশাল, এবং যখন সি ++ 1x উপস্থিত হবে, তখন এটি ব্যাপকভাবে প্রসারিত হবে। এটি অনেকগুলি টাইপ এবং আরও কয়েক বছরের মধ্যে প্রসারিত। আমি মনে করি এটি কন্টেন্টের পরিবর্তে উত্তরাধিকার বিবেচনা করার একটি ভাল কারণ - যদি কেউ এই ভিত্তি অনুসরণ করে যে এই ফাংশনগুলি সদস্য হওয়া উচিত (যা আমি সন্দেহ করি)। এসটিএল ধারকগুলি থেকে প্রাপ্ত না হওয়ার নিয়মটি হ'ল এগুলি বহুকর্মী নয়। আপনি যদি সেভাবে সেগুলি ব্যবহার না করেন তবে এটি প্রয়োগ হয় না।
sbi

9
প্রশ্নের আসল মাংস এক বাক্যে রয়েছে: "আমি তাদের সরাসরি ভেক্টরের সদস্য হতে চাই"। প্রশ্নে অন্য কিছুই আসলেই গুরুত্বপূর্ণ নয়। আপনি এটি "চান" কেন? অ-সদস্য হিসাবে কেবল এই কার্যকারিতাটি সরবরাহ করতে সমস্যা কি?
জাল্ফ

8
@ জোসসি: "আপনি" সর্বদা "আপনি যাবেন" এর চেয়ে বেশি সাধারণ ছিলেন এবং এটি কিং জেমস বাইবেলেও পাওয়া যায় (যা সাধারণত লোকেরা "যখন লেখেন" আপনি কি করবেন না [...] ")। পৃথিবীর কোন বিষয় আপনাকে এটিকে "ভুল বানান" বলতে পরিচালিত করবে?
রুখ

উত্তর:


155

আসলে, জনসাধারণের উত্তরাধিকার নিয়ে কোনও ভুল নেই std::vector। আপনার যদি এটির প্রয়োজন হয় তবে এটি করুন।

আমি শুধুমাত্র যদি তা না হয় যে করছেন সুপারিশ করবে সত্যিই প্রয়োজনীয়। নিখরচায় ফাংশন দিয়ে আপনি যা করতে চান তা করতে না পারলে (যেমন কিছুটা অবস্থা রাখা উচিত)।

সমস্যাটি হ'ল MyVectorনতুন সত্তা। এর অর্থ একটি নতুন সি ++ বিকাশকারী এটি ব্যবহারের আগে এটি কী তা জানতে হবে। মধ্যে পার্থক্য কি std::vectorএবং MyVector? কোনটি এখানে এবং সেখানে ব্যবহার করা ভাল? আমি যদি সরানো প্রয়োজন std::vectorথেকে MyVector? আমি কি শুধু ব্যবহার swap()করতে পারি না?

আরও ভাল কিছু দেখানোর জন্য নতুন সত্ত্বা তৈরি করবেন না। এই সত্তাগুলি (বিশেষত, এই জাতীয়) শূন্যে বাস করবে না। তারা ক্রমাগত বর্ধিত এন্ট্রপি সহ মিশ্র পরিবেশে বাস করবে।


7
আমার এটার একমাত্র জবাবদিহিটি হ'ল যে এটি করতে তিনি কী করছেন তা সত্যই একজনকে অবশ্যই জানতে হবে। উদাহরণস্বরূপ, অতিরিক্ত ডেটা সদস্যদের মধ্যে প্রবর্তন করবেন নাMyVector এবং তারপরে এটি গ্রহণযোগ্য std::vector&বা এমন ফাংশনে এটি দেওয়ার চেষ্টা করুন std::vector*। যদি স্ট্যান্ড :: ভেক্টর * বা এসটিডি :: ভেক্টর & ব্যবহার করে কোনও ধরণের অনুলিপি নিয়োগের সাথে জড়িত থাকে, তবে আমাদের নতুন সমস্যাযুক্ত সমস্যা রয়েছে যেখানে এর নতুন ডেটা সদস্যদের MyVectorঅনুলিপি করা হবে না। বেস পয়েন্টার / রেফারেন্সের মাধ্যমে অদলবদল কল করার ক্ষেত্রেও একই কথা ঘটে। আমি ভাবার প্রবণতা করি যে কোনও ধরণের উত্তরাধিকারের শ্রেণিবিন্যাস যা বস্তুর কাটাকে ঝুঁকিপূর্ণ করে তোলে তা খারাপ।
stinky472

13
std::vectorএর ডেস্ট্রাক্টর নয় virtual, অতএব আপনার কাছ থেকে কখনই উত্তরাধিকারী হওয়া উচিত নয়
আন্দ্রে ফ্রেটেলি

2
আমি একটি ক্লাস তৈরি করেছি যা এই কারণে প্রকাশ্যে std :: ভেক্টরকে উত্তরাধিকার সূত্রে প্রাপ্ত হয়েছিল: আমার একটি নন-এসটিএল ভেক্টর শ্রেণীর সাথে পুরানো কোড ছিল এবং আমি এসটিএল-এ যেতে চেয়েছিলাম। Std :: ভেক্টর ব্যবহার করে নতুন কোড লেখার সময় আমি পুরাতন শ্রেণিকে std :: ভেক্টরের উত্পন্ন ক্লাস হিসাবে পুনরায় প্রয়োগ করেছি, আমাকে পুরানো কোডে পুরানো ফাংশন নামগুলি (যেমন, আকার () এর পরিবর্তে কাউন্ট () গণনা চালিয়ে যাওয়ার অনুমতি দিয়েছি ফাংশন। আমি কোনও ডেটা সদস্য যুক্ত করিনি, অতএব std :: ভেক্টরের ডেস্ট্রাক্টর স্তূপে তৈরি বস্তুর জন্য ভাল কাজ করেছে।
গ্রাহাম আশের

3
@ গ্রাহামআশার যদি আপনি কোনও পয়েন্টারের ভিত্তিতে বেসটি মুছতে পারেন এবং ধ্বংসকারী ভার্চুয়াল না হন তবে আপনার প্রোগ্রামটি অপরিজ্ঞাত আচরণ প্রদর্শন করছে। অপরিবর্তিত আচরণের একটি সম্ভাব্য ফলাফল হ'ল "এটি আমার পরীক্ষায় ভাল কাজ করেছে"। আর একটি হ'ল এটি আপনার দাদীকে আপনার ওয়েব ব্রাউজিংয়ের ইতিহাস ইমেল করে। উভয়ই সি ++ স্ট্যান্ডার্ডের সাথে অনুগত। সংকলক, ওএস বা চাঁদের পর্বের পয়েন্ট রিলিজের সাথে এটি এক থেকে অন্যটিতে পরিবর্তিত হয় l
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

2
@ গ্রাহামআশার না, যখনই আপনি ভার্চুয়াল ডেস্ট্রাক্টর ব্যতীত কোনও পয়েন্টারের মাধ্যমে কোনও অবজেক্ট মুছবেন, এটি স্ট্যান্ডার্ডের অধীনে অপরিবর্তিত আচরণ। আপনারা যা মনে করছেন তা আমি বুঝতে পেরেছি; আপনি ঠিক ভুল হতে। "বেস ক্লাসের ডেস্ট্রাক্টর বলা হয়, এবং এটি কাজ করে" এই অপরিবর্তিত আচরণের একটি সম্ভাব্য লক্ষণ (এবং সর্বাধিক প্রচলিত), কারণ এটি সেই নির্লজ্জ মেশিন কোড যা সংকলক সাধারণত উত্পন্ন করে। এটি এটি নিরাপদ করে না বা করার জন্য দুর্দান্ত ধারণা তৈরি করে না।
ইয়াক্ক - অ্যাডাম নেভ্রামামন্ট

92

পুরো এসটিএলটি এমনভাবে ডিজাইন করা হয়েছিল যাতে অ্যালগরিদম এবং পাত্রে পৃথক হয়

এটি বিভিন্ন ধরণের পুনরাবৃত্তির ধারণার দিকে পরিচালিত করে: কনট পুনরুক্তিকারী, এলোমেলো প্রবেশের পুনরাবৃত্তি ইত্যাদি।

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

এছাড়াও, আমি আপনাকে জেফ অ্যাটউডের কিছু ভাল মন্তব্যে পুনর্নির্দেশ করি ।


63

থেকে উত্তরাধিকার সূত্রে না পাওয়ার মূল কারণ std::vectorসর্বজনীনভাবে হ'ল ভার্চুয়াল ডেস্ট্রাক্টরের অনুপস্থিতি যা কার্যকরভাবে আপনাকে বংশধরদের বহুমুখী ব্যবহার থেকে বিরত করে। বিশেষ করে, আপনি হয় মঞ্জুরিপ্রাপ্ত নয় করার deleteএকটি std::vector<T>*একটি উদ্ভূত বস্তু (এমনকি যদি উদ্ভূত বর্গ কোনো সদস্য যোগ করা) এ যে আসলে পয়েন্ট, এখনো কম্পাইলার সাধারণত এটা সম্পর্কে আপনাকে সতর্ক করতে পারবে না।

এই অবস্থার অধীনে ব্যক্তিগত উত্তরাধিকার অনুমোদিত। অতএব আমি নীচে দেখানো হিসাবে ব্যক্তিগত উত্তরাধিকার ব্যবহার এবং পিতামাতার কাছ থেকে প্রয়োজনীয় পদ্ধতি ফরোয়ার্ড করার পরামর্শ দিচ্ছি।

class AdVector: private std::vector<double>
{
    typedef double T;
    typedef std::vector<double> vector;
public:
    using vector::push_back;
    using vector::operator[];
    using vector::begin;
    using vector::end;
    AdVector operator*(const AdVector & ) const;
    AdVector operator+(const AdVector & ) const;
    AdVector();
    virtual ~AdVector();
};

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


আইআইইউসি, কোনও ভার্চুয়াল ডেস্ট্রাক্টরের অনুপস্থিতি কেবল তখনই সমস্যা হতে পারে যদি উদ্ভূত শ্রেণি সম্পদ বরাদ্দ করে যা ধ্বংসের পরে মুক্ত হতে হবে। (পলিমারফিক ব্যবহারের ক্ষেত্রে তাদের মুক্তি দেওয়া হবে না কারণ প্রসঙ্গটি অজান্তে পয়েন্টারের মাধ্যমে ভিত্তিযুক্ত অবজেক্টের মালিকানা বেসে আনার সময় কেবল বেস ডেস্ট্রাক্টরকে ডেকে আনবে Similar) অন্যান্য ওভাররাইড হওয়া সদস্য ফাংশনগুলি থেকে অনুরূপ সমস্যা দেখা দেয়, তাই যত্ন অবশ্যই করতে হবে বেস যে কল করতে বৈধ তা গ্রহণ করা হবে। কিন্তু অতিরিক্ত সংস্থান অনুপস্থিত, অন্য কোন কারণ আছে?
পিটার - মনিকা পুনরায়

2
vectorএর বরাদ্দকৃত স্টোরেজটি সমস্যা নয় - সর্বোপরি, vectorএর ডেস্ট্রাক্টরকে পয়েন্টারের মাধ্যমে ঠিক ডাকা হবে vector। এটা ঠিক যে স্ট্যান্ডার্ডটি কোনও বেস শ্রেণীর এক্সপ্রেশনের মাধ্যমে ফ্রি স্টোর অবজেক্টগুলিকেdelete ইনগ্রেট করতে নিষেধ করে। কারণটি অবশ্যই হ'ল (ডি) বরাদ্দ প্রক্রিয়া মেমরির খণ্ডের আকারটি 'অপারেন্ড' থেকে মুক্ত করতে চেষ্টা করতে পারে উদাহরণস্বরূপ যখন নির্দিষ্ট আকারের অবজেক্টের জন্য বেশ কয়েকটি বরাদ্দ আখড়া থাকে। এই সীমাবদ্ধতা, আফিক্স, স্থির বা স্বয়ংক্রিয় স্টোরেজ সময়কাল সহ অবজেক্টগুলির স্বাভাবিক ধ্বংসের ক্ষেত্রে প্রযোজ্য নয়। delete
পিটার - মনিকা

@ ডেভিস হেরিং আমার মনে হয় আমরা সেখানে সম্মত :-)।
পিটার - মনিকা

@ ডেভিস হেরিং আহ, আমি দেখছি, আপনি আমার প্রথম মন্তব্যটি উল্লেখ করেছেন - সেই মন্তব্যে একটি আইআইইউসি ছিল, এবং এটি একটি প্রশ্নে শেষ হয়েছিল; আমি পরে দেখেছি যে এটি অবশ্যই সর্বদা নিষিদ্ধ। (বাসিলিভস একটি সাধারণ বিবৃতি দিয়েছিলেন, "কার্যকরভাবে প্রতিরোধ করে", এবং এটি যে নির্দিষ্ট উপায়ে এটি প্রতিরোধ করে সে সম্পর্কে আমি অবাক হয়েছি)) সুতরাং হ্যাঁ, আমরা সম্মত: ইউবি।
পিটার - মনিকাকে

@ বাসিলিভগুলি অবশ্যই অজান্তেই থাকতে পারে। সংশোধন করা হয়েছে।
থমাসম্যাকলিউড

36

যদি আপনি এটি বিবেচনা করছেন, আপনি ইতিমধ্যে স্পষ্টভাবে আপনার অফিসে ভাষা শিক্ষকদের হত্যা করেছেন sla তাদের সাথে উপায় ছাড়িয়ে যান, কেন শুধু করবেন না

struct MyVector
{
   std::vector<Thingy> v;  // public!
   void func1( ... ) ; // and so on
}

এটি ঘটনাক্রমে আপনার মাইভেক্টর ক্লাসটিকে উপকৃত করে তুলতে পারে এমন সমস্ত সম্ভাব্য ত্রুটিগুলি ছাপিয়ে যাবে এবং আপনি কেবল কিছুটা যোগ করে সমস্ত ভেক্টর অপ্স অ্যাক্সেস করতে পারবেন .v


এবং পাত্রে এবং অ্যালগরিদমগুলি উন্মোচন করছেন? উপরে কোসের উত্তর দেখুন।
ব্রুনো nery


19

আপনি কি অর্জন আশা করছেন? শুধু কিছু কার্যকারিতা সরবরাহ?

এটির জন্য সি ++ অহংকারিক উপায় হ'ল কিছু ফাংশন লিখুন যা কার্যকারিতা কার্যকর করে। সম্ভাবনাগুলি হ'ল বিশেষত আপনার কোনও স্টাডি :: ভেক্টর দরকার নেইআপনার বাস্তবায়নের যে কার্যকারিতা বাস্তবায়নের জন্য হ'ল মানে আপনি স্ট্যান্ড :: ভেক্টর থেকে উত্তরাধিকারী হওয়ার চেষ্টা করে পুনরায় ব্যবহারযোগ্যতা হারাচ্ছেন।

আমি আপনাকে স্ট্যান্ডার্ড লাইব্রেরি এবং শিরোনামগুলি দেখুন এবং তারা কীভাবে কাজ করে সে সম্পর্কে ধ্যান করার জন্য দৃ strongly়ভাবে পরামর্শ দেব।


5
আমি সন্তুষ্ট নই. আপনি কিছু প্রস্তাবিত কোড দিয়ে আপডেট করতে পারেন কেন তা ব্যাখ্যা করার জন্য?
কার্ল নচেটেল

6
@ আর্মেন: নান্দনিকতা বাদে কি কোনও ভাল কারণ আছে?
স্নেমার্চ

12
@ আর্মেন: উন্নত নান্দনিকতা এবং বৃহত্তর উদারতা হ'ল বিনামূল্যে frontএবং backকার্যাদিও সরবরাহ করা। :) (এছাড়াও ফ্রি beginএবং endসি ++ 0
এক্স

3
ফ্রি ফাংশনগুলিতে আমি এখনও ভুল করছি না don't আপনি যদি এসটিএলের "নান্দনিকতা" পছন্দ করেন না, তবে সি ++ আপনার পক্ষে নান্দনিকভাবে ভুল জায়গা। এবং কিছু সদস্য ফাংশন যুক্ত করা এটি ঠিক করবে না, যতটা অন্যান্য অ্যালগোরিদম এখনও ফ্রি ফাংশন।
ফ্র্যাঙ্ক ওস্টারফিল্ড

17
বাহ্যিক অ্যালগরিদমে ভারী অপারেশনের ফলে ক্যাশে করা শক্ত। ধরুন আপনাকে ভেক্টরের সমস্ত উপাদানগুলির একটি যোগফল গণনা করতে হবে বা ভেক্টর উপাদানগুলির সহগ হিসাবে একটি বহুবর্ষ সমীকরণ সমাধান করতে হবে। এই অপারেশনগুলি ভারী এবং অলসতা তাদের জন্য কার্যকর হবে। তবে আপনি ধারক থেকে মোড়ানো বা উত্তরাধিকারসূত্রে ছাড়াই এটি পরিচয় করিয়ে দিতে পারবেন না।
বেসিলিভস

14

আমি মনে করি খুব কম নিয়মগুলি 100% সময় অন্ধভাবে অনুসরণ করা উচিত। দেখে মনে হচ্ছে আপনি এটিকে বেশ চিন্তাভাবনা করেছেন, এবং আপনি নিশ্চিত হন যে এটিই যাওয়ার উপায়। সুতরাং - যদি না কেউ এই না করার জন্য নির্দিষ্ট নির্দিষ্ট কারণ নিয়ে আসে - আমি মনে করি আপনার পরিকল্পনাটি নিয়ে এগিয়ে যাওয়া উচিত।


9
আপনার প্রথম বাক্যটি সময়ের 100% সত্য। :)
স্টিভ

5
দুর্ভাগ্যক্রমে, দ্বিতীয় বাক্যটি তা নয়। তিনি এটাকে অনেক চিন্তাভাবনা করেননি। বেশিরভাগ প্রশ্নই অপ্রাসঙ্গিক। এর একমাত্র অংশ যা তার অনুপ্রেরণা দেখায় তা হ'ল "আমি তাদের সরাসরি ভেক্টরের সদস্য হতে চাই"। আমি চাই. কেন এটি পছন্দসই কারণ নেই । যা দেখে মনে হচ্ছে তিনি এটিকে কিছুতেই ভাবেননি
জাল্ফ

7

উত্তরাধিকারী হওয়ার কোনও কারণ নেই যদি না যে কেউ তার std::vectorচেয়ে আলাদাভাবে কাজ করে এমন একটি শ্রেণী তৈরি করতে চায় std::vector, কারণ এটি তার নিজস্ব std::vectorসংজ্ঞায়নের গোপন বিশদটি নিজের মতো করে পরিচালনা করে , বা যদি না কারও কাছে এই শ্রেণীর অবজেক্টগুলিকে ব্যবহারের মতাদর্শগত কারণ না থাকে std::vectorএর। তবে, সি ++ এর মানদণ্ডের নির্মাতারা std::vectorকোনও ইন্টারফেস (সুরক্ষিত সদস্যের আকারে) সরবরাহ করেন নি যে এই জাতীয় উত্তরাধিকার সূত্রে প্রাপ্ত শ্রেণি নির্দিষ্টভাবে ভেক্টরকে উন্নত করার জন্য সুবিধা নিতে পারে। প্রকৃতপক্ষে, তাদের কোনও নির্দিষ্ট ভাবার উপায় ছিল না দিক সম্পর্কে এক্সটেনশন বা জরিমানা অতিরিক্ত প্রয়োগের প্রয়োজন হতে পারে, সুতরাং তাদের কোনও উদ্দেশ্যে এই জাতীয় ইন্টারফেস সরবরাহ করার কথা ভাবার দরকার ছিল না।

দ্বিতীয় বিকল্পের কারণগুলি কেবলমাত্র মতাদর্শিক হতে পারে, কারণ std::vectorএটি বহুবর্ষীয় নয়, এবং অন্যথায় আপনি std::vectorজনসাধারণের উত্তরাধিকারের মাধ্যমে বা জনসাধারণের সদস্যপদ মাধ্যমে প্রকাশ্যে পাবলিক ইন্টারফেস প্রকাশ করেছেন কিনা তাতে কোনও পার্থক্য নেই । (ধরুন আপনার অবজেক্টে কিছু স্থিতি রাখা দরকার যাতে আপনি নিখরচায় ফাংশন দিয়ে পালাতে পারবেন না)। একটি স্বল্প নোটে এবং আদর্শিক দৃষ্টিকোণ থেকে এটি প্রদর্শিত হয় যে এটি std::vectorএক ধরণের "সাধারণ ধারণা", সুতরাং তাদের জায়গায় বিভিন্ন সম্ভাব্য শ্রেণীর বস্তুর আকারে যে কোনও জটিলতা আদর্শিকভাবে কোনও উপকার করে না।


দুর্দান্ত উত্তর। তাই আপনাকে স্বাগতম!
আর্মেন ​​সিরুনিয়ান

4

ব্যবহারিক পদে: আপনার উত্পন্ন শ্রেণিতে যদি আপনার কোনও ডেটা সদস্য না থাকে তবে আপনার কোনও সমস্যা নেই, এমনকি পলিমারফিক ব্যবহারেও নয়। আপনার কেবলমাত্র ভার্চুয়াল ডেস্ট্রাক্টর প্রয়োজন যদি বেস ক্লাস এবং উত্পন্ন শ্রেণীর আকারগুলি আলাদা হয় এবং / অথবা আপনার ভার্চুয়াল ফাংশন (যার অর্থ একটি ভি-টেবিল) থাকে।

তাত্ত্বিকভাবে কিন্তু: বাট সি ++ 0 এক্স এফসিডিতে [এক্সপ্রেসড্রেলেট] থেকে: প্রথম বিকল্পে (অবজেক্ট মুছুন), যদি মুছে ফেলা অবজেক্টের স্ট্যাটিক টাইপটি তার গতিশীল প্রকারের থেকে পৃথক হয়, স্থির প্রকারটি হবে মুছে ফেলার জন্য গতিশীল ধরণের অবজেক্টের বেস ক্লাস এবং স্ট্যাটিক টাইপের ভার্চুয়াল ডেস্ট্রাক্টর থাকতে হবে বা আচরণটি অপরিবর্তিত।

তবে আপনি কোনও সমস্যা ছাড়াই স্টাড :: ভেক্টর থেকে গোপনীয়তা অর্জন করতে পারেন। আমি নিম্নলিখিত প্যাটার্ন ব্যবহার করেছি:

class PointVector : private std::vector<PointType>
{
    typedef std::vector<PointType> Vector;
    ...
    using Vector::at;
    using Vector::clear;
    using Vector::iterator;
    using Vector::const_iterator;
    using Vector::begin;
    using Vector::end;
    using Vector::cbegin;
    using Vector::cend;
    using Vector::crbegin;
    using Vector::crend;
    using Vector::empty;
    using Vector::size;
    using Vector::reserve;
    using Vector::operator[];
    using Vector::assign;
    using Vector::insert;
    using Vector::erase;
    using Vector::front;
    using Vector::back;
    using Vector::push_back;
    using Vector::pop_back;
    using Vector::resize;
    ...

3
"বেস ক্লাস এবং উত্পন্ন শ্রেণীর আকারগুলি বিভিন্ন ন্যাড / অথবা আপনার ভার্চুয়াল ফাংশন (যার অর্থ একটি ভি-টেবিল) থাকে তবে আপনার কেবল ভার্চুয়াল ডেস্ট্রাক্টর প্রয়োজন" " এই দাবিটি ব্যবহারিকভাবে সঠিক, তবে তাত্ত্বিকভাবে নয়
আর্মেন ​​সিরুনিয়ান

2
হ্যাঁ, নীতিগতভাবে এটি এখনও অপরিবর্তিত আচরণ।
জাল্ফ

আপনি যদি দাবি করেন যে এটি অনির্ধারিত আচরণ বলে আমি একটি প্রমাণ দেখতে চাই (মানক থেকে উদ্ধৃতি)।
হুমেলনার

8
@ হুমুয়েলার: দুর্ভাগ্যক্রমে, আর্মেন ​​এবং জাল্ফ এই বিষয়ে সঠিক। থেকে [expr.delete]সি ++ 0x FCD মধ্যে: <উদ্ধৃতি> প্রথম বিকল্প (ডিলিট বস্তুর), যদি বস্তুর স্ট্যাটিক টাইপ মুছে যাবে তার গতিশীল টাইপ থেকে আলাদা, স্ট্যাটিক টাইপ গতিশীল ধরনের একটি বেস বর্গ হইবে অবজেক্টটি মুছতে হবে এবং স্থির ধরণের কোনও ভার্চুয়াল ডেস্ট্রাক্টর থাকতে হবে বা আচরণটি অপরিবর্তিত রয়েছে </ </ quote>
বেন ভয়েগট

1
কোনটি মজার, কারণ আমি ভেবেছিলাম যে আচরণটি একটি তুচ্ছ ত্রুটিযুক্ত ডেস্ট্রাক্টরের উপস্থিতির উপর নির্ভরশীল (বিশেষত, পিওডি ক্লাসগুলি পয়েন্টার-টু-বেসের মাধ্যমে ধ্বংস করা যেতে পারে)।
বেন ভয়েগট

3

আপনি যদি ভাল সি ++ স্টাইল অনুসরণ করেন তবে ভার্চুয়াল ফাংশনের অনুপস্থিতি সমস্যা নয়, তবে কাটছে (দেখুন https://stackoverflow.com/a/14461532/877329 )

ভার্চুয়াল ফাংশনগুলির অনুপস্থিতি কেন সমস্যা নয়? কারণ কোনও ফাংশন deleteএটি প্রাপ্ত কোনও পয়েন্টারের চেষ্টা করা উচিত নয় , কারণ এটির এর কোনও মালিকানা নেই। অতএব, কঠোর মালিকানার নীতিগুলি অনুসরণ করে যদি ভার্চুয়াল ধ্বংসকারীদের প্রয়োজন হয় না। উদাহরণস্বরূপ, এটি সর্বদা ভুল (ভার্চুয়াল ডেস্ট্রাক্টর সহ বা না):

void foo(SomeType* obj)
    {
    if(obj!=nullptr) //The function prototype only makes sense if parameter is optional
        {
        obj->doStuff();
        }
    delete obj;
    }

class SpecialSomeType:public SomeType
    {
    // whatever 
    };

int main()
    {
    SpecialSomeType obj;
    doStuff(&obj); //Will crash here. But caller does not know that
//  ...
    }

বিপরীতে, এটি সর্বদা কাজ করবে (ভার্চুয়াল ডেস্ট্রাক্টর সহ বা ছাড়াই):

void foo(SomeType* obj)
    {
    if(obj!=nullptr) //The function prototype only makes sense if parameter is optional
        {
        obj->doStuff();
        }
    }

class SpecialSomeType:public SomeType
    {
    // whatever 
    };

int main()
    {
    SpecialSomeType obj;
    doStuff(&obj);
//  The correct destructor *will* be called here.
    }

যদি কোনও কারখানার দ্বারা অবজেক্টটি তৈরি করা হয়, তবে কারখানার একটি কার্যকারী ডিফল্টারে একটি পয়েন্টারও ফেরত দেওয়া উচিত, যা পরিবর্তে ব্যবহার করা উচিত delete, কারখানাটি তার নিজস্ব গাদা ব্যবহার করতে পারে। কলকারী এটি share_ptrবা এর রূপ পেতে পারে unique_ptr। সংক্ষেপে বলতে গেলে, না deleteকিছু আপনি পাননি সরাসরি থেকে new


2

হ্যাঁ এটি সুরক্ষিত যতক্ষণ না আপনি নিরাপদ জিনিসগুলি না করার বিষয়ে সতর্ক হন ... আমি মনে করি না যে আমি কখনও কাউকে নতুন দিয়ে ভেক্টর ব্যবহার করতে দেখেছি অনুশীলনে আপনি সম্ভবত ভাল থাকবেন। তবে এটি সি ++ তে সাধারণ প্রতিমা নয় i

আপনি কি অ্যালগরিদমগুলি সম্পর্কে আরও তথ্য দিতে সক্ষম?

কখনও কখনও আপনি নকশা সহ একটি রাস্তায় নেমে শেষ করেন এবং তারপরে আপনি যে অন্য পথগুলি নিয়েছিলেন তা দেখতে পাচ্ছেন না - আপনি যে সত্যটি আমার জন্য 10 টি নতুন অ্যালগরিদমের রিং অ্যালার্ম ঘণ্টা দিয়ে ভেক্টর লাগানোর দাবি করেছেন - সেখানে কি 10 টি সাধারণ উদ্দেশ্য আছে? অ্যালগরিদম যা ভেক্টর বাস্তবায়ন করতে পারে, বা আপনি এমন কোনও বস্তু তৈরি করার চেষ্টা করছেন যা উভয়ই সাধারণ উদ্দেশ্য ভেক্টর এবং যার মধ্যে অ্যাপ্লিকেশন নির্দিষ্ট ফাংশন রয়েছে?

আমি অবশ্যই বলছি না যে আপনার এটি করা উচিত নয়, এটি কেবলমাত্র আপনি যে তথ্য দিয়েছিলেন তার সাথে অ্যালার্মের ঘণ্টা বাজছে যা আমাকে মনে করে যে সম্ভবত আপনার বিমূর্তে কিছু ভুল হয়েছে এবং আপনি যা অর্জন করার একটি আরও ভাল উপায় আছে চাই।


2

আমি std::vectorসাম্প্রতিককালেও উত্তরাধিকার সূত্রে পেয়েছি এবং এটি খুব দরকারী বলে খুঁজে পেয়েছি এবং এখন পর্যন্ত আমি এটির সাথে কোনও সমস্যা পাইনি।

আমার ক্লাসটি একটি বিচ্ছিন্ন ম্যাট্রিক্স ক্লাস, যার অর্থ আমার ম্যাট্রিক্স উপাদানগুলি কোথাও, যেমন একটিতে সঞ্চয় করা দরকার std::vector। উত্তরাধিকার সূত্রে আমার কারণ হ'ল যে আমি সমস্ত পদ্ধতিতে ইন্টারফেস লিখতে কিছুটা অলস ছিলাম এবং এসডিজিআইজি এর মাধ্যমে পাইথনে ক্লাসটি ইন্টারফেস করছি, যেখানে ইতিমধ্যে ভাল ইন্টারফেস কোড রয়েছে std::vector। স্ক্র্যাচ থেকে একটি নতুন লেখার চেয়ে আমার ক্লাসে এই ইন্টারফেস কোডটি প্রসারিত করা অনেক সহজ বলে মনে হয়েছিল।

একমাত্র সমস্যা আমি পদ্ধতির দেখতে পারেন এত অ ভার্চুয়াল বিনাশকারী সঙ্গে নয়, বরং যেমন কিছু অন্যান্য পদ্ধতি, যা আমি জমিদার চাই, push_back(), resize(), insert()ইত্যাদি ব্যক্তিগত উত্তরাধিকার প্রকৃতপক্ষে একটি ভালো বিকল্প হতে পারে।

ধন্যবাদ!


10
আমার অভিজ্ঞতায়, সবচেয়ে খারাপ দীর্ঘমেয়াদী ক্ষতি প্রায়শই লোকজন দ্বারা ঘটে থাকে যারা খারাপ পরামর্শ দেওয়ার চেষ্টা করে এবং " এখনও পর্যন্ত এটির সাথে কোনও সমস্যায় পড়েনি ( লক্ষ্য করুন পড়ুন )"।
বিভ্রান্ত

0

এখানে, আপনি চান আপনার আরও 2 টি উপায়ের সাথে পরিচয় করিয়ে দিন। একটি মোড়ানোর অন্য উপায় std::vector, অন্যটি হ'ল ব্যবহারকারীদের কিছু ভাঙার সুযোগ না দিয়ে উত্তরাধিকারের উপায়:

  1. আমাকে std::vectorপ্রচুর ফাংশন র‍্যাপারগুলি না লিখে মোড়ানোর অন্য একটি উপায় যুক্ত করুন ।

#include <utility> // For std:: forward
struct Derived: protected std::vector<T> {
    // Anything...
    using underlying_t = std::vector<T>;

    auto* get_underlying() noexcept
    {
        return static_cast<underlying_t*>(this);
    }
    auto* get_underlying() const noexcept
    {
        return static_cast<underlying_t*>(this);
    }

    template <class Ret, class ...Args>
    auto apply_to_underlying_class(Ret (*underlying_t::member_f)(Args...), Args &&...args)
    {
        return (get_underlying()->*member_f)(std::forward<Args>(args)...);
    }
};
  1. পরিবর্তে স্ট্যান্ড :: স্প্যান থেকে std::vectorউত্তোলন এবং ড্টরের সমস্যা এড়ানো।

0

এই প্রশ্নটি শ্বাস-প্রশ্বাস মুক্তো-ছোঁয়া উত্পাদন গ্যারান্টিযুক্ত, কিন্তু আসলে একটি স্ট্যান্ডার্ড ধারক থেকে উদ্ভূত এড়ানো, বা "অযৌক্তিকরূপে সত্তা গুণ" এড়ানোর জন্য কোন কারণ সনাক্ত করা যায় না। সবচেয়ে সহজ, সংক্ষিপ্ততম সম্ভাব্য অভিব্যক্তিটি পরিষ্কার এবং সর্বোত্তম।

যে কোনও উদ্ভূত প্রকারের চারপাশে আপনার সমস্ত স্বাভাবিক যত্ন অনুশীলন করা দরকার, তবে স্ট্যান্ডার্ড থেকে বেসের ক্ষেত্রে বিশেষ কিছু নেই। একটি বেস সদস্য ফাংশন ওভাররাইড করা জটিল হতে পারে, তবে এটি কোনও অ-ভার্চুয়াল বেসের সাথে করা বুদ্ধিমানের কাজ হবে, সুতরাং এখানে খুব বেশি বিশেষ কিছু নেই। আপনি যদি কোনও ডেটা সদস্য যুক্ত করতে চান তবে সদস্যকে বেসের বিষয়বস্তুগুলির সাথে সামঞ্জস্য রাখতে হলে কাটা কাটা সম্পর্কে আপনাকে চিন্তিত হতে হবে, তবে এটি কোনও বেসের জন্য একই is

বিশেষভাবে কার্যকর স্ট্যান্ডার্ড থেকে যে জায়গাটি আমি পেয়েছি তা হ'ল এমন একক কন্সট্রাক্টর যুক্ত করা যা সঠিকভাবে প্রাথমিকভাবে প্রয়োজনীয় আরম্ভের প্রয়োজন হয়, অন্য কনস্ট্রাক্টর দ্বারা বিভ্রান্তি বা হাইজ্যাকের কোনও সম্ভাবনা ছাড়াই। (আমি আপনার দিকে লক্ষ্য করছি, আর্টিনিয়েশন_লিস্ট কনস্ট্রাক্টর!) তারপরে, আপনি নিখরচায় ফলস্বরূপ অবজেক্টটি কাটা কাটা কাটা ব্যবহার করতে পারেন - বেসটি প্রত্যাশা করে এমন কিছু উল্লেখ করে এটি পাস করুন, এটি থেকে বেসের উদাহরণে চলে যান, আপনার কী আছে। উদ্বেগ করার জন্য কোনও প্রান্তের কেস নেই, যদি না এটি আপনাকে উদ্ভূত শ্রেণীর কাছে কোনও টেম্পলেট যুক্তি বাঁধতে বিরক্ত করে।

এমন এক জায়গা যেখানে এই কৌশলটি তত্ক্ষণাত সি ++ ২০ তে কার্যকর হবে তা হল রিজার্ভেশন। যেখানে আমরা লিখতে পারে

  std::vector<T> names; names.reserve(1000);

আমরা বলতে পারেন

  template<typename C> 
  struct reserve_in : C { 
    reserve_in(std::size_t n) { this->reserve(n); }
  };

এবং তারপরে, এমনকি ক্লাসের সদস্য হিসাবে,

  . . .
  reserve_in<std::vector<T>> taken_names{1000};  // 1
  std::vector<T> given_names{reserve_in<std::vector<T>>{1000}}; // 2
  . . .

(পছন্দ অনুসারে) এবং তাদের উপর কেবল রিজার্ভ () কল করতে কোনও কনস্ট্রাক্টর লেখার দরকার নেই।

(যে কারণে reserve_in, প্রযুক্তিগতভাবে, সি ++ 20 এর জন্য অপেক্ষা করা দরকার তা হ'ল পূর্বের স্ট্যান্ডার্ডগুলিতে খালি ভেক্টরের সক্ষমতা প্রয়োজনে চলনগুলি ধরে রাখার দরকার নেই That এটি একটি তদারকি হিসাবে স্বীকৃত, এবং যুক্তিসঙ্গতভাবে এটি স্থির হওয়ার আশা করা যেতে পারে '20 এর সময় মতো ত্রুটি হিসাবে। আমরা পূর্বের স্ট্যান্ডার্ডগুলিতে কার্যকরভাবে পিছনে ফিরে আসার প্রত্যাশাও করতে পারি, কারণ সমস্ত বিদ্যমান বাস্তবায়নগুলি বাস্তবে পদক্ষেপের বাইরে ক্ষমতা সংরক্ষণ করে; স্ট্যান্ডার্ডগুলি কেবল এটির প্রয়োজন হয় না। আগ্রহীরা নিরাপদে লাফিয়ে উঠতে পারে বন্দুক - সংরক্ষণ প্রায় সবসময় যাইহোক যাইহোক কেবলমাত্র একটি অপ্টিমাইজেশন))

কিছু তর্ক করবে যে কেস reserve_inএকটি ভাল ফাংশন টেম্পলেট দ্বারা আরও ভাল পরিবেশিত হয়:

  template<typename C> 
  auto reserve_in(std::size_t n) { C c; c.reserve(n); return c; }

এই জাতীয় বিকল্পটি অবশ্যই কার্যকর - এবং এমনকি * আরভিওর কারণে অনেক সময় অসীম দ্রুতও হতে পারে। তবে ডেরাইভেশন বা ফ্রি ফাংশনের পছন্দটি নিজস্ব গুণাবলীর ভিত্তিতে করা উচিত, স্ট্যান্ডার্ড উপাদানগুলি থেকে প্রাপ্ত সম্পর্কে ভিত্তিহীন (হি!) কুসংস্কার থেকে নয়। উপরের উদাহরণে ব্যবহার করুন, কেবলমাত্র দ্বিতীয় ফর্মটি ফ্রি ফাংশন সহ কাজ করবে; যদিও শ্রেণি প্রসঙ্গে বাইরে এটি আরও কিছুটা সংক্ষিপ্তভাবে লেখা যেতে পারে:

  auto given_names{reserve_in<std::vector<T>>(1000)}; // 2
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.