কেন অনন্য_সত্তার <বিসর্জন> অনন্য_আপনার <বাসে> তে অন্তর্ভুক্ত?


21

আমি নিম্নলিখিত কোডটি লিখেছিলাম unique_ptr<Derived>যেখানে unique_ptr<Base>এটি প্রত্যাশিত হয় uses

class Base {
    int i;
 public:
    Base( int i ) : i(i) {}
    int getI() const { return i; }
};

class Derived : public Base {
    float f;
 public:
    Derived( int i, float f ) : Base(i), f(f) {}
    float getF() const { return f; }
};

void printBase( unique_ptr<Base> base )
{
    cout << "f: " << base->getI() << endl;
}

unique_ptr<Base> makeBase()
{
    return make_unique<Derived>( 2, 3.0f );
}

unique_ptr<Derived> makeDerived()
{
    return make_unique<Derived>( 2, 3.0f );
}

int main( int argc, char * argv [] )
{
    unique_ptr<Base> base1 = makeBase();
    unique_ptr<Base> base2 = makeDerived();
    printBase( make_unique<Derived>( 2, 3.0f ) );

    return 0;
}

এবং আমি এই কোডটি সংকলন না করার প্রত্যাশা করেছি, কারণ আমার বোঝাপড়া অনুসারে unique_ptr<Base>এবং unique_ptr<Derived>অসম্পৃক্ত ধরণের এবং unique_ptr<Derived>বাস্তবে উত্পন্ন নয় unique_ptr<Base>যাতে অ্যাসাইনমেন্টটি কাজ না করে।

তবে কিছু জাদুতে এটি কাজ করে বলে ধন্যবাদ এবং আমি কেন বুঝতে পারি না বা এটি করা নিরাপদ থাকলেও। কেউ দয়া করে ব্যাখ্যা করতে পারেন?


3
স্মার্ট পয়েন্টারগুলি হ'ল সমৃদ্ধ করতে হবে যে পয়েন্টারগুলি এটি সীমাবদ্ধ করতে পারে না। যদি এটি সম্ভব unique_ptrনা হয় তবে উত্তরাধিকারের উপস্থিতিতে অকেজো হতে হবে
idclev 463035818

3
"তবে ধন্যবাদ কিছু যাদুতে এটি কাজ করে" । প্রায়, আপনি ইউবি পেয়েছেন যেমন Baseভার্চুয়াল ডেস্ট্রাক্টর নেই।
জারোড 42

উত্তর:


25

আপনি যে জাদুটির সন্ধান করছেন তা হ'ল রূপান্তরকারী কনস্ট্রাক্টর # 6 এখানে :

template<class U, class E>
unique_ptr(unique_ptr<U, E> &&u) noexcept;

এটি std::unique_ptr<T>মেয়াদ উত্তীর্ণ হওয়া থেকে একটি স্পষ্টভাবে নির্মাণ সক্ষম করে std::unique_ptr<U> যদি (স্পষ্টতার জন্য মুছে ফেলার জন্য চকচকে):

unique_ptr<U, E>::pointer স্পষ্টত রূপান্তরিত হয় pointer

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


2
আফিকের মুছে ফেলা ডিস্ট্রাক্টরকে Baseকল করবে না Derived, তাই এটি সত্যই নিরাপদ কিনা তা আমি নিশ্চিত নই। (এটি কাঁচা পয়েন্টারের চেয়ে কম নিরাপদ নয়, স্বীকার
করেই

14

কারণ std::unique_ptrহিসাবে একটি রূপান্তরকারী নির্মাণকারী আছে

template< class U, class E >
unique_ptr( unique_ptr<U, E>&& u ) noexcept;

এবং

এই নির্মাণকারী কেবলমাত্র ওভারলোড রেজোলিউশনে অংশ নেয় যদি নীচের সমস্তগুলি সত্য হয়:

ক) unique_ptr<U, E>::pointerস্পষ্টত রূপান্তরিত হয়pointer

...

এ সুস্পষ্টভাবে Derived*রূপান্তর করতে পারে Base*, তবে রূপান্তরকারী কনস্ট্রাক্টর এই ক্ষেত্রে আবেদন করা যেতে পারে। তারপরে একটি কাঁচা পয়েন্টার যেমন হয় তেমন std::unique_ptr<Base>কোনও রূপান্তরিত হতে পারে std::unique_ptr<Derived>। (মনে রাখবেন যে এর বৈশিষ্ট্যটির কারণে এটি std::unique_ptr<Derived>নির্মাণের মূল্য হতে হবে ))std::unique_ptr<Base>std::unique_ptr


7

আপনি করতে পারেন পরোক্ষভাবে একটি গঠন করা std::unique_ptr<T>একটি থেকে উদাহরণস্বরূপ rvalue এর std::unique_ptr<S>যখনই Sকরার পরিবর্তনীয় হয় T। এটি এখানে কনস্ট্রাক্টরের # 6 কারণে রয়েছে । এক্ষেত্রে মালিকানা স্থানান্তরিত হয়।

আপনার উদাহরণে, আপনার কেবল প্রকারের std::uinque_ptr<Derived>মূল্য রয়েছে (কারণ এর ফেরতের মানটি std::make_uniqueএকটি মূল্যমান) এবং আপনি যখন এটি হিসাবে ব্যবহার করেন std::unique_ptr<Base>, উপরে বর্ণিত কনস্ট্রাক্টরটি আহ্বান করা হয়। std::unique_ptr<Derived>সুতরাং প্রশ্নে থাকা অবজেক্টগুলি কেবল অল্প সময়ের জন্যই বেঁচে থাকে, অর্থাত্ সেগুলি তৈরি হয়, তারপরে মালিকানা সেই std::unique_ptr<Base>বস্তুর কাছে প্রেরণ করা হয় যা আরও ব্যবহৃত হয়।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.