বস্তু কাটা কি?


উত্তর:


608

"স্লাইসিং" হ'ল যেখানে আপনি একটি বর্গ শ্রেণীর উদাহরণকে উত্পন্ন শ্রেণীর একটি অবজেক্ট অর্পণ করেন, যার ফলে তথ্যের কিছু অংশ হারাতে থাকে - এর কিছু "দূরে স্লাইসড" থাকে।

উদাহরণ স্বরূপ,

class A {
   int foo;
};

class B : public A {
   int bar;
};

সুতরাং প্রকারের একটি বস্তু Bদুটি ডেটা সদস্য রয়েছে, fooএবং bar

আপনি যদি এটি লিখতে চান তবে:

B b;

A a = b;

তারপরে bসদস্য সম্পর্কে তথ্য barহারিয়ে যায় a



55
মজাদার. আমি ১৫ বছর ধরে সি ++ তে প্রোগ্রামিং করছি এবং এই সমস্যাটি আমার কাছে কখনও আসেনি, কারণ আমি দক্ষতা এবং ব্যক্তিগত স্টাইলের বিষয়টি হিসাবে রেফারেন্স দিয়ে সর্বদা অবজেক্টগুলি পাস করেছি। কীভাবে ভাল অভ্যাস আপনাকে সহায়তা করতে পারে তা দেখানোর জন্য যায়।
কার্ল বিলেফেল্ট

10
@Felix ধন্যবাদ কিন্তু আমি ফিরে (একটি পয়েন্টার এরিথমেটিক দেখাও) ভোটদান কাজ করবে বলে মনে করি না A a = b; aধরনের বস্তু এখন Aযার কপি আছে B::foo। এটি এখনই ফেলে দেওয়া ভুল হবে এখন আমার ধারণা।

37
এটি "স্লাইসিং" নয়, বা এটির কমপক্ষে একটি সৌম্য বৈকল্পিক। আসল সমস্যাটি যদি ঘটে তবেই ঘটে B b1; B b2; A& b2_ref = b2; b2 = b1। আপনি মনে করতে পারেন আপনি অনুলিপি b1করেছেন b2, তবে আপনি তা করেন নি! আপনি একটি অনুলিপি করেছেন অংশ এর b1জন্য b2(অংশ b1যে Bথেকে উত্তরাধিকারসূত্রে A), এবং অন্যান্য অংশ বাম b2অপরিবর্তিত। b2এখন একটি খোলামেলা প্রাণী যা কিছু বিট b1দ্বারা গঠিত এবং এর কিছু অংশ রয়েছে b2। ইসস! ডাউনভোটিং কারণ আমি মনে করি উত্তরটি খুব মিসলাইডিং।
fgp

24
@fgp আপনার মন্তব্যটি পড়তে হবে B b1; B b2; A& b2_ref = b2; b2_ref = b1" যদি আপনি আসল সমস্যা দেখা দেয় " ... একটি অ-ভার্চুয়াল অ্যাসাইনমেন্ট অপারেটর সহ একটি শ্রেণি থেকে প্রাপ্ত। হয় Aএমনকি শিক্ষাদীক্ষা জন্য দেয়ার উদ্দেশ্যে করা? এটির কোনও ভার্চুয়াল ফাংশন নেই। আপনি যদি কোনও প্রকার থেকে উদ্ভূত হন তবে আপনাকে তার সদস্য ফাংশনগুলি বলা যেতে পারে এই বিষয়টি মোকাবেলা করতে হবে!
কৌতূহলী

508

এখানে বেশিরভাগ উত্তর স্লাইসিংয়ের সাথে আসল সমস্যাটি কী তা ব্যাখ্যা করতে ব্যর্থ হয়। এগুলি কেবল কাটা কাটানোর সৌম্য মামলাগুলি ব্যাখ্যা করে, বিশ্বাসঘাতকরা নয়। অন্যান্য উত্তরগুলির মতো, ধরে নিন যে আপনি দুটি শ্রেণী নিয়ে কাজ করছেন Aএবং Bযেখানে Bথেকে (প্রকাশ্যে) এসেছে A

এ অবস্থায় সি ++ তোমাদের একটি দৃষ্টান্ত পাস করতে দেয় Bকরার A'র নিয়োগ অপারেটর (এবং কপি কন্সট্রাকটর করার জন্য)। এটি কাজ করে কারণ একটি উদাহরণকে Bএকটিতে রূপান্তর করা যায় const A&যা কার্যনির্বাহক অপারেটর এবং অনুলিপি-নির্মাতারা তাদের যুক্তিগুলি প্রত্যাশা করে।

সৌম্য মামলা

B b;
A a = b;

সেখানে খারাপ কিছু হয় না - আপনি একটি উদাহরণ চেয়েছিলেন Aযার একটি অনুলিপি Bএবং আপনি ঠিক এটি পেয়েছেন। অবশ্যই, এর সদস্যদের aকিছু থাকবে না b, তবে এটি কীভাবে করা উচিত? এটি একটি A, সর্বোপরি, একটি নয় B, তাই এটি এই সদস্যদের সম্পর্কে এমনকি শোনেনি , একাকী তাদের সংরক্ষণ করতে সক্ষম হবে।

বিশ্বাসঘাতক মামলা

B b1;
B b2;
A& a_ref = b2;
a_ref = b1;
//b2 now contains a mixture of b1 and b2!

আপনি ভাবতে পারেন যে b2এটি b1পরে একটি অনুলিপি হবে । কিন্তু হায়, এটা না ! আপনি যদি এটি পরীক্ষা করেন, আপনি আবিষ্কার করতে পারবেন যে b2এটি একটি ফ্রাঙ্কেনস্টেইনীয় প্রাণী, কিছু অংশ থেকে তৈরি b1(অংশগুলি যা Bউত্তরাধিকার সূত্রে প্রাপ্ত A) এবং কিছু কিছু অংশ b2(কেবলমাত্র অংশগুলি Bরয়েছে) সেকি!

কি হলো? ভাল, সি ++ ডিফল্টরূপে অ্যাসাইনমেন্ট অপারেটরদের হিসাবে বিবেচনা করে না virtual। সুতরাং, লাইনটি a_ref = b1অ্যাসাইনমেন্ট অপারেটরকে কল করবে, এটির Aনয় B। এটি কারণ, অ-ভার্চুয়াল ফাংশনগুলির জন্য, ঘোষিত (আনুষ্ঠানিকভাবে: স্ট্যাটিক ) প্রকারটি (যা A&) নির্ধারণ করে যে কোন ফাংশনটি বলা হয়, প্রকৃত (আনুষ্ঠানিকভাবে: গতিশীল ) প্রকারের বিপরীতে (যা হবে B, যেহেতু a_refউদাহরণ হিসাবে উল্লেখ করা হয় B) । এখন, Aঅ্যাসাইনমেন্ট অপারেটর স্পষ্টভাবে কেবল ঘোষিত সদস্যদের সম্পর্কেই জানে A, সুতরাং এটি কেবল তাদের অনুলিপি করবে, সদস্যদের Bঅপরিবর্তিত রেখে দেওয়া হবে ।

একটি সমাধান

কেবলমাত্র কোনও বস্তুর অংশগুলিতে অর্পণ করা সাধারণত সামান্য অর্থবোধ করে, তবুও দুর্ভাগ্যক্রমে, সি ++ এটিকে নিষিদ্ধ করার কোনও অন্তর্নির্মিত উপায় সরবরাহ করে না। আপনি তবে নিজের রোল করতে পারেন। প্রথম পদক্ষেপটি অ্যাসাইনমেন্ট অপারেটরটিকে ভার্চুয়াল করে তুলছে । এটি গ্যারান্টি দিবে যে এটি সর্বদা আসল টাইপের অ্যাসাইনমেন্ট অপারেটর যাকে বলা হয়, ঘোষিত ধরণের নয় । দ্বিতীয় পদক্ষেপটি dynamic_castযাচাই করা অবজেক্টটি একটি সামঞ্জস্যপূর্ণ টাইপ আছে তা যাচাই করতে ব্যবহার করা হয়। তৃতীয় ধাপ একটি (সংরক্ষিত!) সদস্য প্রকৃত নিয়োগ করতে হয় assign(), যেহেতু Bএর assign()সম্ভবত ব্যবহার করতে চান হবে A's assign()কপি করতে Aএর, সদস্য।

class A {
public:
  virtual A& operator= (const A& a) {
    assign(a);
    return *this;
  }

protected:
  void assign(const A& a) {
    // copy members of A from a to this
  }
};

class B : public A {
public:
  virtual B& operator= (const A& a) {
    if (const B* b = dynamic_cast<const B*>(&a))
      assign(*b);
    else
      throw bad_assignment();
    return *this;
  }

protected:
  void assign(const B& b) {
    A::assign(b); // Let A's assign() copy members of A from b to this
    // copy members of B from b to this
  }
};

মনে রাখবেন যে, খাঁটি সুবিধার জন্য, Bএর operator=সমবায়ীরা রিটার্নের ধরণটিকে ওভাররাইড করে, যেহেতু এটি জানে যে এটি একটি উদাহরণ ফিরে আসছে B


11
আইএমএইচও, সমস্যাটি হ'ল দুটি পৃথক প্রকারের সাবস্টিটিবিলিটি যা উত্তরাধিকারের দ্বারা বোঝানো যেতে পারে: হয় কোনও derivedমান মান প্রত্যাশী কোডকে দেওয়া যেতে পারে base, বা কোনও উত্পন্ন রেফারেন্স বেস রেফারেন্স হিসাবে ব্যবহার করা যেতে পারে। আমি একটি টাইপ সিস্টেমের সাথে একটি ভাষা দেখতে চাই যা উভয় ধারণাকে পৃথকভাবে সম্বোধন করে। অনেকগুলি ক্ষেত্রে রয়েছে যেখানে উত্পন্ন রেফারেন্সটি বেস রেফারেন্সের পরিবর্তে পরিবর্তনযোগ্য হওয়া উচিত, তবে উত্পন্ন উদাহরণগুলি বেসের জন্য পরিবর্তিতযোগ্য হওয়া উচিত নয়; এমন অনেকগুলি ঘটনা রয়েছে যেখানে দৃষ্টান্তগুলি রূপান্তরযোগ্য হওয়া উচিত তবে রেফারেন্সগুলির বিকল্প হওয়া উচিত নয়।
সুপারক্যাট

16
আপনার "বিশ্বাসঘাতক" মামলায় কী খারাপ তা আমি বুঝতে পারি না। আপনি বলেছিলেন যে আপনি: ১) শ্রেণি A এবং 2 এর একটি অবজেক্টের রেফারেন্স পেতে চান) অবজেক্ট বি 1 কে ক্লাস এ এ কাস্ট করুন এবং এর স্টাফটি ক্লাস এ এর ​​রেফারেন্সে অনুলিপি করুন এখানে আসলে যা ভুল তা পিছনে যথাযথ যুক্তি প্রদত্ত কোড অন্য কথায়, আপনি একটি ছোট চিত্রের ফ্রেম (এ) নিয়েছেন, এটি একটি বড় চিত্র (বি) এর উপরে রেখেছেন এবং আপনি সেই ফ্রেমের মাধ্যমে আঁকেন, পরে অভিযোগ করেছেন যে আপনার বড় চিত্রটি এখন কুৎসিত দেখাচ্ছে :) তবে আমরা যদি কেবল ফ্রেমযুক্ত অঞ্চলটি বিবেচনা করি, এটি দেখতে বেশ সুন্দর দেখাচ্ছে ঠিক যেমন চিত্রশিল্পী চেয়েছিলেন, তাই না? :)
ম্লাদেন বি

12
ডিফল্টরূপে সি ++++++++++++++++++ ++++++++++++++++++++++++++ ডিফল্টরূপে সি ++ টি খুব শক্তিশালী ধরণের সাবস্টিটেবলিয়াকে ধরে নেয় - এর জন্য সাবক্লাসের উদাহরণগুলিতে সঠিকভাবে কাজ করার জন্য বেস ক্লাসের ক্রিয়াকলাপ প্রয়োজন। এবং এটি এমনকি অপারেশনগুলির জন্য যা সংকলক অ্যাসাইনমেন্টের মতো স্বয়ংক্রিয়ভাবে তৈরি করে। সুতরাং এই ক্ষেত্রে আপনার নিজের ক্রিয়াকলাপ স্ক্রু না করাই যথেষ্ট নয়, আপনাকে সংকলক দ্বারা উত্পন্ন ভুলগুলিও স্পষ্টভাবে অক্ষম করতে হবে। অথবা অবশ্যই, সর্বজনীন উত্তরাধিকার থেকে দূরে থাকুন, যা সাধারণতঃ আগেই ভাল পরামর্শ ;-)
fgp

14
আর একটি সাধারণ পদ্ধতি হ'ল অনুলিপিটি অনুলিপি করুন উত্তরাধিকার শ্রেণিবিন্যাসের ক্লাসগুলির জন্য, সাধারণত রেফারেন্স বা পয়েন্টারের পরিবর্তে মান ব্যবহার করার কোনও কারণ নেই।
সিয়ুয়ান রেন

13
কি? আমার কোনও ধারণা ছিল না অপারেটরগুলিকে ভার্চুয়াল হিসাবে চিহ্নিত করা যেতে পারে
পলম

153

আপনার যদি একটি বেস ক্লাস Aএবং একটি উত্পন্ন ক্লাস থাকে Bতবে আপনি নিম্নলিখিতটি করতে পারেন।

void wantAnA(A myA)
{
   // work with myA
}

B derived;
// work with the object "derived"
wantAnA(derived);

এখন পদ্ধতিটির wantAnAএকটি অনুলিপি প্রয়োজন derived। তবে বস্তুটি derivedসম্পূর্ণ অনুলিপি করা যায় না, কারণ শ্রেণিটি Bঅতিরিক্ত সদস্য ভেরিয়েবলগুলি আবিষ্কার করতে পারে যা তার বেস শ্রেণিতে নেই A

অতএব, কল করার জন্য wantAnA, সংকলক উদ্ভূত শ্রেণীর সমস্ত অতিরিক্ত সদস্যদের "স্লাইস অফ" করবে। ফলাফল এমন কোনও বস্তু হতে পারে যা আপনি তৈরি করতে চাননি, কারণ

  • এটি অসম্পূর্ণ হতে পারে,
  • এটি একটি- Aঅবজেক্টের মতো আচরণ করে (শ্রেণীর সমস্ত বিশেষ আচরণ Bহারিয়ে গেছে)।

40
সি ++ জাভা নয় ! যদি wantAnA(এর নাম অনুসারে!) একটি চায় A, তবে এটি যা পায় it এবং একটি উদাহরণ A, ইচ্ছা, আহ মত আচরণ করে A। কীভাবে অবাক হয়?
fgp

82
@ এফজিপি: অবাক করা কারণ আপনি ফাংশনে একটি এ পাস করেন না
কালো

10
@fgp: আচরণটি একই রকম। তবে, গড় সি ++ প্রোগ্রামার এটি কম সুস্পষ্ট হতে পারে। আমি যতদূর প্রশ্নটি বুঝতে পেরেছি, কেউই "অভিযোগ" করছে না। সংকলক পরিস্থিতিটি কীভাবে পরিচালনা করে তা ঠিক। তবে, রেফারেন্স (কনস্ট্যান্ট) পাস করে কাটা কাটা এড়ানো ভাল avoid
কালো

8
@ থমাসডাব্লু না, আমি উত্তরাধিকার ছাড়ব না, তবে উল্লেখগুলি ব্যবহার করব। যদি ওয়ান্টএএনএ এর স্বাক্ষর যদি অকার্যকর চায়না (কনস্ট এ এবং মাইএ) হয়ে থাকে , তবে সেখানে টুকরো টুকরো টুকরো টুকরো টুকরো টুকরো টান ছিল না। পরিবর্তে, কলারের অবজেক্টের কেবল পঠনযোগ্য রেফারেন্সটি পাস হয়ে যায়।
কালো

14
সমস্যাটি বেশিরভাগই স্বয়ংক্রিয়ভাবে onালাইয়ের ক্ষেত্রে থাকে যা সংকলক থেকে derivedটাইপ করে A। অন্তর্নিহিত ingালাই সর্বদা সি ++ তে অপ্রত্যাশিত আচরণের উত্স, কারণ স্থানীয়ভাবে কোডটি স্থান পেয়েছে এমন কোডটি দেখে বোঝা প্রায়শই শক্ত।
pqnet

41

এগুলি সব ভাল উত্তর। রেফারেন্স অনুসারে মান দ্বারা বনাম বস্তুগুলি পাস করার সময় আমি একটি কার্যকরকরণের উদাহরণটি যুক্ত করতে চাই:

#include <iostream>

using namespace std;

// Base class
class A {
public:
    A() {}
    A(const A& a) {
        cout << "'A' copy constructor" << endl;
    }
    virtual void run() const { cout << "I am an 'A'" << endl; }
};

// Derived class
class B: public A {
public:
    B():A() {}
    B(const B& a):A(a) {
        cout << "'B' copy constructor" << endl;
    }
    virtual void run() const { cout << "I am a 'B'" << endl; }
};

void g(const A & a) {
    a.run();
}

void h(const A a) {
    a.run();
}

int main() {
    cout << "Call by reference" << endl;
    g(B());
    cout << endl << "Call by copy" << endl;
    h(B());
}

আউটপুটটি হ'ল:

Call by reference
I am a 'B'

Call by copy
'A' copy constructor
I am an 'A'

হ্যালো. দুর্দান্ত উত্তর তবে আমার একটি প্রশ্ন আছে। আমি যদি এরকম কিছু করি ** দেব ডি; বেস * খ = & ডি; ** টুকরো টুকরোও হয়?
অ্যাড্রিয়ান

@ অ্যাড্রিয়ান আপনি যদি উদ্ভূত শ্রেণিতে কিছু নতুন সদস্য ফাংশন বা সদস্য ভেরিয়েবল প্রবর্তন করেন তবে সেগুলি সরাসরি বেস বর্গ পয়েন্টার থেকে অ্যাক্সেসযোগ্য নয়। তবে আপনি এখনও ওভারলোডেড বেস শ্রেণীর ভার্চুয়াল ফাংশনগুলির ভিতরে থেকে এগুলি অ্যাক্সেস করতে পারেন। এটি দেখুন: Godbolt.org/z/LABx33
বিশাল শর্মা

30

"সি ++ স্লাইসিং" এর জন্য গুগলের তৃতীয় ম্যাচটি আমাকে এই উইকিপিডিয়া নিবন্ধটি http://en.wikedia.org/wiki/Object_slicing এবং এটি দেয় (উত্তপ্ত, তবে প্রথম কয়েকটি পোস্ট সমস্যার সংজ্ঞা দেয়): http://bytes.com/ ফোরাম / thread163565.html

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

যদি এই লিঙ্কগুলি কোনও "ভাল উত্তর" দেওয়ার জন্য পর্যাপ্ত তথ্য না দেয় তবে দয়া করে আপনার আরও কী সন্ধান করছেন তা আমাদের জানানোর জন্য আপনার প্রশ্নটি সম্পাদনা করুন।


29

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

A বিভাগটি বিবেচনা করুন এবং এ থেকে উত্পন্ন ক্লাস বিটি এ এর ​​অংশের একটি পয়েন্টার পি, এবং একটি খ উদাহরণ রয়েছে যা বি এর অতিরিক্ত ডেটাতে পয়েন্ট করে মেমরি দুর্নীতি হতে পারে। তারপরে, অতিরিক্ত তথ্য বিচ্ছিন্ন হয়ে গেলে, পি আবর্জনার দিকে নির্দেশ করছে।


3
কীভাবে স্মৃতি দুর্নীতি হতে পারে তা দয়া করে ব্যাখ্যা করুন।
foraidt

4
আমি ভুলে গিয়েছিলাম যে অনুলিপি কর্নটি ভিটিপিআরটিকে পুনরায় সেট করবে, আমার ভুল। তবে এ এর ​​একটি পয়েন্টার থাকলে আপনি এখনও দুর্নীতি পেতে পারেন, এবং বি সেট করে যে বি এর অংশে নির্দেশ করে s
ওয়াল্টার উজ্জ্বল

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

2
@ উইয়েবল - এজন্য আপনি এই ক্ষেত্রে ডিফল্ট ডেস্ট্রাক্টর, অ্যাসাইনমেন্ট অপারেটর এবং অনুলিপি-নির্মাণকারীকে ওভাররাইড করেন।
বার্জারে ফ্রেন্ড-হানসেন

7
@ ওয়েবেল: সাধারণ পয়েন্টার ফিক্সআপগুলির চেয়ে অবজেক্ট স্লাইসিংয়ের চেয়ে খারাপটি কী করে তা হ'ল এটি নিশ্চিত হওয়া উচিত যে আপনি কাটা কাটা কাটা আটকাতে বাধা দিয়েছেন, একটি বেস শ্রেণিকে অবশ্যই প্রতিটি উত্পন্ন শ্রেণীর জন্য রূপান্তরকারী কনস্ট্রাক্টর সরবরাহ করতে হবে । (কেন? যে কোনও উদ্ভূত ক্লাসগুলি মিস হয়েছে তা বেস ক্লাসের কপি কর্টারের কাছ থেকে বাছাই করা সংবেদনশীল, যেহেতু Derivedএটি স্পষ্টভাবে রূপান্তরিত Base।) এটি স্পষ্টতই উন্মুক্ত-বন্ধ নীতিটির বিপরীতে এবং একটি বড় রক্ষণাবেক্ষণের বোঝা।
j_random_hacker

10

সি ++ তে, একটি উত্পন্ন শ্রেণি অবজেক্টকে বেস শ্রেণীর বস্তুকে বরাদ্দ করা যেতে পারে, তবে অন্য উপায়টি সম্ভব নয়।

class Base { int x, y; };

class Derived : public Base { int z, w; };

int main() 
{
    Derived d;
    Base b = d; // Object Slicing,  z and w of d are sliced off
}

অবজেক্ট স্লাইসিংয়ের ঘটনা ঘটে যখন কোনও উত্পন্ন শ্রেণীর অবজেক্টটি একটি বেস শ্রেণীর অবজেক্টকে অর্পণ করা হয়, একটি উত্পন্ন শ্রেণীর অবজেক্টের অতিরিক্ত বৈশিষ্ট্যগুলি বেস শ্রেণীর অবজেক্টটি গঠনের জন্য কেটে ফেলা হয়।


8

সি ++ এ টুকরো টুকরো টুকরো টুকরো সমস্যা এর বস্তুর মান শব্দার্থতত্ত্ব থেকে উদ্ভূত, যা বেশিরভাগ সি স্ট্রকের সাথে সামঞ্জস্যতার কারণে থেকে যায়। বেশিরভাগ অন্যান্য ভাষায় যে বস্তুগুলি ব্যবহার করে, অর্থাৎ বস্তুগুলিকে সর্বদা রেফারেন্সের মাধ্যমে অতিক্রম করা হয় তার মধ্যে পাওয়া "স্বাভাবিক" অবজেক্ট আচরণ অর্জনের জন্য আপনাকে সুস্পষ্ট রেফারেন্স বা পয়েন্টার সিনট্যাক্স ব্যবহার করতে হবে।

সংক্ষিপ্ত উত্তরগুলি হ'ল আপনি মানটিকে ভিত্তি করে কোনও অবৈধ বস্তুকে একটি উত্পন্ন বস্তু বরাদ্দ করে বস্তুটি টুকরো টুকরো করেন , অর্থাত্ বাকী অবজেক্টটি প্রাপ্ত হওয়া অবজেক্টের একটি অংশ মাত্র। মান শব্দার্থ সংরক্ষণের জন্য, স্লাইসিং একটি যুক্তিসঙ্গত আচরণ এবং এর অপেক্ষাকৃত বিরল ব্যবহার রয়েছে, যা বেশিরভাগ অন্যান্য ভাষায় নেই। কিছু লোক এটিকে সি ++ এর বৈশিষ্ট্য হিসাবে বিবেচনা করে, আবার অনেকে এটিকে C ++ এর অন্যতম বাতুলতা / অপব্যবহার বলে বিবেচনা করে।


5
" " সাধারণ "অবজেক্ট আচরণ " এটি "সাধারণ অবজেক্ট আচরণ" নয়, এটিই রেফারেন্স সিমেটিক । এবং এটা সম্পর্কিত কোন ভাবেই সি সঙ্গে struct, সামঞ্জস্য, অথবা অন্য অ-ইন্দ্রিয় কোন র্যান্ডম গলি যাজক তোমাকে বলেছিলাম।
কৌতূহলী

4
@ কুরিয়াসগুই আমেন, ভাই। জাভা না হয়ে কতবার সি ++ ভিত্তি করা হয় তা দেখার জন্য দুঃখ হয়, যখন মান শব্দার্থক জিনিসগুলি এমন একটি বিষয় যা সি ++ এত উন্মত্তভাবে শক্তিশালী করে তোলে।
fgp

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

অবশ্যই সি ++ এর একটি অপব্যবহার। ভিত্তি অবজেক্টে একটি উত্পন্ন বস্তুকে বরাদ্দ করা নিষিদ্ধ করা উচিত, যখন একটি উত্স বা ভিত্তি শ্রেণীর পয়েন্টারের সাথে ডাইরেক্ট করা অবজেক্টকে আবদ্ধ করা ঠিক হবে।
জন জেড। লি

7

সুতরাং ... প্রাপ্ত তথ্য হারানো কেন খারাপ? ... কারণ উত্পন্ন শ্রেণীর লেখক এমন উপস্থাপনা পরিবর্তন করতে পারেন যে অতিরিক্ত তথ্য কাটলে বস্তুর দ্বারা প্রতিনিধিত্ব করা মানকে পরিবর্তন করে। যদি উদ্ভূত শ্রেণীর কোনও উপস্থাপনা ক্যাশে ব্যবহৃত হয় যা নির্দিষ্ট ক্রিয়াকলাপের জন্য আরও দক্ষ, তবে বেস উপস্থাপনায় ফিরে যেতে ব্যয়বহুল হয় তবে এটি ঘটতে পারে।

এছাড়াও ভেবেছিল কেউ কাটা কাটা এড়াতে আপনার কী করা উচিত তাও উল্লেখ করা উচিত ... সি ++ কোডিং স্ট্যান্ডার্ডস, 101 টি বিধি নির্দেশিকা এবং সেরা অনুশীলনের একটি অনুলিপি পান। স্লাইসিংয়ের সাথে ডিলিং হচ্ছে # 54।

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

আপনি অনুলিপি বেসটি অনুলিপিতে অনুলিপি করতে পারেন যা এটি পছন্দসই হলে স্পষ্টভাবে কাটানোর জন্য অনুমতি দেয়।


3
" আপনি বেসটি স্পষ্ট করে অনুলিপি নির্ধারণকারীটিকেও চিহ্নিত করতে পারেন " যা মোটেই সহায়তা করে না
কৌতূহলী

6

1. স্লাইসিং সমস্যা সংজ্ঞা

ডি যদি বেস শ্রেণি বি এর উদ্ভূত বর্গ হয়, তবে আপনি বেস টাইপের ভেরিয়েবল (বা পরামিতি) থেকে ডেরিভেড টাইপের একটি অবজেক্ট বরাদ্দ করতে পারেন।

EXAMPLE টি

class Pet
{
 public:
    string name;
};
class Dog : public Pet
{
public:
    string breed;
};

int main()
{   
    Dog dog;
    Pet pet;

    dog.name = "Tommy";
    dog.breed = "Kangal Dog";
    pet = dog;
    cout << pet.breed; //ERROR

যদিও উপরের অ্যাসাইনমেন্টের অনুমতি দেওয়া হয়েছে, তবে ভেরিয়েবল পোষা প্রাণীর কাছে নির্ধারিত মান তার জাতের ক্ষেত্রটি হারাতে পারে। একে স্লাইসিং প্রব্লেম বলে ।

২. কীভাবে সমস্যা সমাধান করতে পারেন?

সমস্যাটিকে পরাস্ত করতে আমরা গতিশীল ভেরিয়েবলের পয়েন্টার ব্যবহার করি।

EXAMPLE টি

Pet *ptrP;
Dog *ptrD;
ptrD = new Dog;         
ptrD->name = "Tommy";
ptrD->breed = "Kangal Dog";
ptrP = ptrD;
cout << ((Dog *)ptrP)->breed; 

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


7
আমি "কাটা" অংশটি বুঝতে পারি, তবে আমি "সমস্যা" বুঝতে পারি না। এটি কীভাবে সমস্যা হয় যে এর কিছু রাজ্য dogশ্রেণীর অংশ নয় Pet( breedডেটা মেম্বার) ভেরিয়েবলে অনুলিপি করে না pet? কোডটি কেবল Petডেটা সদস্যদের মধ্যেই আগ্রহী - দৃশ্যত। কাঁচকাটা অবশ্যই যদি এটি অযাচিত হয় তবে একটি "সমস্যা", তবে আমি এখানে এটি দেখতে পাচ্ছি না।
কৌতূহলী

4
" ((Dog *)ptrP)" আমি ব্যবহার করার পরামর্শ দিচ্ছিstatic_cast<Dog*>(ptrP)
কৌতূহলী

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

24
-1 এটি সম্পূর্ণরূপে আসল সমস্যাটি ব্যাখ্যা করতে ব্যর্থ। সি ++ মান শব্দার্থবিদ্যা হয়েছে না তাই এই সব সম্পূর্ণরূপে আশা করা যেতে পারে, জাভা মত রেফারেন্স শব্দার্থবিদ্যা। এবং "ফিক্স" সত্যই ভয়ঙ্কর সি ++ কোডের একটি উদাহরণ । গতিশীল বরাদ্দের অবলম্বন করে এই ধরণের টুকরো টুকরো করার মতো "অযৌক্তিক সমস্যাগুলি" বগি কোড, ফাঁস স্মৃতি এবং ভয়াবহ পারফরম্যান্সের একটি রেসিপি। নোট যে হয় ক্ষেত্রে যেখানে slicing খারাপ, কিন্তু এই উত্তর failes তাদের নির্দেশ। ইঙ্গিত: সমস্যাটি শুরু হয় যদি আপনি রেফারেন্সের মাধ্যমে বরাদ্দ করেন ।
fgp

আপনি কি বুঝতে পেরেছেন যে সংজ্ঞায়িত নয় এমন ধরণের সদস্য অ্যাক্সেস করার চেষ্টা Dog::breedকরা কোনওভাবেই স্লিকিংয়ের সাথে সম্পর্কিত কোনও ত্রুটি নয়?
ক্রল করুন

4

আমার কাছে মনে হয়, আপনার নিজের ক্লাস এবং প্রোগ্রামটি খারাপভাবে নকশাকৃত / নকশাকৃত হওয়ার পরে কাটা কাটা এত সমস্যা নয়।

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

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


3
তবে মিনোক, মনে রাখবেন যে আপনি সেই অবজেক্টের কোনও রেফারেন্স দিয়ে যাচ্ছেন না। আপনি সেই অবজেক্টের একটি নতুন অনুলিপি পাস করছেন, কিন্তু বেস শ্রেণিটি ব্যবহার করে এটি প্রক্রিয়াটিতে অনুলিপি করছেন।
আরাফ্যাজিওন

বেস ক্লাসে সুরক্ষিত অনুলিপি / অ্যাসাইনমেন্ট এবং এই সমস্যাটি সমাধান করা হয়েছে।
ডুড

1
তুমি ঠিক বলছো. ভালো অভ্যাস হ'ল বিমূর্ত বেস ক্লাসগুলি ব্যবহার করা বা অনুলিপি / অ্যাসাইনমেন্টের অ্যাক্সেসকে সীমাবদ্ধ করা। তবে একবারে এটি উপস্থিতি এত সহজ নয় এবং যত্ন নেওয়া ভুলে যাওয়া সহজ। কাটা * সহ ভার্চুয়াল পদ্ধতিতে কল করা যদি অ্যাক্সেস লঙ্ঘন না করে দূরে সরে যায় তবে এটি রহস্যজনক বিষয়গুলি ঘটতে পারে।
ছেলে

1
আমি বিশ্ববিদ্যালয়ে আমার সি ++ প্রোগ্রামিং কোর্সগুলি থেকে স্মরণ করি যে আমাদের তৈরি প্রতিটি শ্রেণীর জন্য আমাদের ডিফল্ট কনস্ট্রাক্টর, কপি কনস্ট্রাক্টর এবং অ্যাসাইনমেন্ট অপারেটর, পাশাপাশি একজন ডেস্ট্রাক্টর লেখার দরকার ছিল best এই ক্লাসটি লেখার সময় আপনি অনুলিপি তৈরির কাজটি এবং আপনার অনুরোধটি ঠিক যেমন ঘটেছে ঠিক তেমনটি করেছেন ... পরবর্তীকালে কিছু অদ্ভুত আচরণ দেখানোর পরিবর্তে sure
মিনোক

3

ঠিক আছে, আমি বস্তুর স্লাইসিংয়ের ব্যাখ্যা দিয়ে অনেকগুলি পোস্ট পড়ার পরে এটিকে চেষ্টা করব তবে কীভাবে সমস্যাযুক্ত হয় তা নয়।

মেমরির দুর্নীতির পরিণতি ঘটাতে পারে এমন দুষ্ট দৃশ্যটি নিম্নলিখিত:

  • ক্লাস একটি বহুবর্ষীয় বেস শ্রেণিতে অ্যাসাইনমেন্ট সরবরাহ করে (দুর্ঘটনাক্রমে, সম্ভবত সংকলক-উত্পন্ন) provides
  • ক্লায়েন্ট অনুলিপি করা ক্লাসের উদাহরণ এবং অনুলিপি করে।
  • ক্লায়েন্টটি একটি ভার্চুয়াল সদস্য ফাংশনকে কল করে যা কাটা-কাটা অবস্থাটি অ্যাক্সেস করে।

3

টুকরো টুকরো করার অর্থ হ'ল সাবক্লাস দ্বারা যুক্ত করা ডেটা যখন সাবক্লাসের কোনও অবজেক্টকে মান দ্বারা পাস করা হয় বা কোনও বেস ক্লাসের অবজেক্টের প্রত্যাশা করে এমন কোনও ফাংশন থেকে ফেরত দেওয়া হয় তখন তা বাতিল করা হয়।

ব্যাখ্যা: নিম্নলিখিত শ্রেণীর ঘোষণা বিবেচনা করুন:

           class baseclass
          {
                 ...
                 baseclass & operator =(const baseclass&);
                 baseclass(const baseclass&);
          }
          void function( )
          {
                baseclass obj1=m;
                obj1=m;
          }

বেসক্লাসের অনুলিপি ফাংশনগুলি যেমন উত্পন্ন সম্পর্কে কিছুই জানে না কেবলমাত্র প্রাপ্ত ব্যয়ের অংশটি অনুলিপি করা হয়। এটি সাধারণত কাটা হিসাবে উল্লেখ করা হয়।


1
class A 
{ 
    int x; 
};  

class B 
{ 
    B( ) : x(1), c('a') { } 
    int x; 
    char c; 
};  

int main( ) 
{ 
    A a; 
    B b; 
    a = b;     // b.c == 'a' is "sliced" off
    return 0; 
}

4
আপনি কিছু অতিরিক্ত বিবরণ দিতে আপত্তি করতে হবে? ইতিমধ্যে পোস্ট করা উত্তরগুলির চেয়ে আপনার উত্তর কীভাবে আলাদা?
অ্যালেক্সিস কবুতর

2
আমি অনুমান করি যে আরও ব্যাখ্যাটি খারাপ হবে না।
লুপার

-1

যখন একটি উত্পন্ন শ্রেণি অবজেক্টটি একটি বেস শ্রেণীর অবজেক্টকে বরাদ্দ করা হয়, তখন একটি উত্পন্ন শ্রেণীর অবজেক্টের অতিরিক্ত বৈশিষ্ট্যগুলি বিচ্ছিন্ন করে দেওয়া হয় (বাতিল করা হবে) বেস শ্রেণীর অবজেক্টটি গঠন করে।

class Base { 
int x;
 };

class Derived : public Base { 
 int z; 
 };

 int main() 
{
Derived d;
Base b = d; // Object Slicing,  z of d is sliced off
}

-1

যখন একটি ডেরিভেড ক্লাস অবজেক্ট বেস ক্লাস অবজেক্টকে অর্পণ করা হয়, তখন ড্রেভড ক্লাস অবজেক্টের সমস্ত সদস্য বেস ক্লাসে উপস্থিত না থাকা সদস্য ব্যতীত বেস ক্লাস অবজেক্টে অনুলিপি করা হয়। এই সদস্যগুলি সংকলক দ্বারা বিচ্ছিন্ন করা হয়। একে অবজেক্ট স্লাইসিং বলা হয়।

এখানে একটি উদাহরণ:

#include<bits/stdc++.h>
using namespace std;
class Base
{
    public:
        int a;
        int b;
        int c;
        Base()
        {
            a=10;
            b=20;
            c=30;
        }
};
class Derived : public Base
{
    public:
        int d;
        int e;
        Derived()
        {
            d=40;
            e=50;
        }
};
int main()
{
    Derived d;
    cout<<d.a<<"\n";
    cout<<d.b<<"\n";
    cout<<d.c<<"\n";
    cout<<d.d<<"\n";
    cout<<d.e<<"\n";


    Base b = d;
    cout<<b.a<<"\n";
    cout<<b.b<<"\n";
    cout<<b.c<<"\n";
    cout<<b.d<<"\n";
    cout<<b.e<<"\n";
    return 0;
}

এটি উত্পন্ন করবে:

[Error] 'class Base' has no member named 'd'
[Error] 'class Base' has no member named 'e'

ডাউনভোটেড কারণ এটি একটি ভাল উদাহরণ নয়। এটি কাজ করবে না যদি d বি-তে অনুলিপি করার পরিবর্তে, আপনি একটি পয়েন্টার ব্যবহার করবেন যে ক্ষেত্রে d এবং e এখনও বিদ্যমান থাকবে তবে বেসের সেই সদস্য নেই। আপনার উদাহরণটি কেবল দেখায় যে আপনি ক্লাসে নেই এমন সদস্যদের অ্যাক্সেস করতে পারবেন না।
স্টিফান ফ্যাবিয়ান

-2

আমি স্লাইসিং সমস্যাটি পেরিয়ে সরাসরি ততক্ষণে এখানে পৌঁছেছি। সুতরাং আমাকে এই আমার দুটি সেন্ট যোগ করুন।

আসুন "প্রোডাকশন কোড" (বা এমন কিছু আসে যা কিছু ধরণের কাছাকাছি আসে) থেকে নেওয়া যাক:


ধরা যাক আমাদের এমন কিছু আছে যা ক্রিয়া প্রেরণ করে। উদাহরণস্বরূপ একটি নিয়ন্ত্রণ কেন্দ্র ইউআই।
এই ইউআই-তে বর্তমানে প্রেরণে সক্ষম এমন জিনিসগুলির একটি তালিকা পাওয়া দরকার। সুতরাং আমরা প্রেরণ-তথ্য ধারণ করে এমন একটি শ্রেণির সংজ্ঞা দিই। এটি কল করুন Action। সুতরাং একটি Actionকিছু সদস্য ভেরিয়েবল আছে। সরলতার জন্য আমাদের আছে মাত্র ২, একটি std::string nameএবং একটি std::function<void()> f। তারপরে এটি একটি void activate()যা কেবল fসদস্যকে কার্যকর করে।

তাই ইউআই std::vector<Action>সরবরাহ সরবরাহ করে। কিছু ফাংশন কল্পনা করুন:

void push_back(Action toAdd);

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

সুতরাং লোকটি Actionতার নিজস্ব গন্ধ যুক্ত করতে এসেছে ।
তিনি তার বাসগৃহের ক্লাসের একটি উদাহরণটি পাস করেন push_backতবে তারপরে প্রোগ্রামটি হাইওয়াইরে যায়।

তাহলে কি হয়েছে?
আপনি যেমন অনুমান করতে পারেন: অবজেক্টটি কাটা হয়েছে।

উদাহরণ থেকে অতিরিক্ত তথ্য হারিয়ে গেছে, এবং fএখন অপরিজ্ঞাত আচরণের প্রবণ।


আমি আশা করি যে এই উদাহরণগুলি সেই সমস্ত লোকদের জন্য আলোকপাত করেছে যারা Aএস এবং Bএস সম্পর্কে কিছু কথাবার্তা বলার সময় সত্যিই জিনিসগুলি কল্পনা করতে পারে না ।

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