আইআরসি-তে কেউ কাটানোর সমস্যা হিসাবে উল্লেখ করেছে।
আইআরসি-তে কেউ কাটানোর সমস্যা হিসাবে উল্লেখ করেছে।
উত্তর:
"স্লাইসিং" হ'ল যেখানে আপনি একটি বর্গ শ্রেণীর উদাহরণকে উত্পন্ন শ্রেণীর একটি অবজেক্ট অর্পণ করেন, যার ফলে তথ্যের কিছু অংশ হারাতে থাকে - এর কিছু "দূরে স্লাইসড" থাকে।
উদাহরণ স্বরূপ,
class A {
int foo;
};
class B : public A {
int bar;
};
সুতরাং প্রকারের একটি বস্তু B
দুটি ডেটা সদস্য রয়েছে, foo
এবং bar
।
আপনি যদি এটি লিখতে চান তবে:
B b;
A a = b;
তারপরে b
সদস্য সম্পর্কে তথ্য bar
হারিয়ে যায় a
।
A a = b;
a
ধরনের বস্তু এখন A
যার কপি আছে B::foo
। এটি এখনই ফেলে দেওয়া ভুল হবে এখন আমার ধারণা।
B b1; B b2; A& b2_ref = b2; b2 = b1
। আপনি মনে করতে পারেন আপনি অনুলিপি b1
করেছেন b2
, তবে আপনি তা করেন নি! আপনি একটি অনুলিপি করেছেন অংশ এর b1
জন্য b2
(অংশ b1
যে B
থেকে উত্তরাধিকারসূত্রে A
), এবং অন্যান্য অংশ বাম b2
অপরিবর্তিত। b2
এখন একটি খোলামেলা প্রাণী যা কিছু বিট b1
দ্বারা গঠিত এবং এর কিছু অংশ রয়েছে b2
। ইসস! ডাউনভোটিং কারণ আমি মনে করি উত্তরটি খুব মিসলাইডিং।
B b1; B b2; A& b2_ref = b2; b2_ref = b1
" যদি আপনি আসল সমস্যা দেখা দেয় " ... একটি অ-ভার্চুয়াল অ্যাসাইনমেন্ট অপারেটর সহ একটি শ্রেণি থেকে প্রাপ্ত। হয় A
এমনকি শিক্ষাদীক্ষা জন্য দেয়ার উদ্দেশ্যে করা? এটির কোনও ভার্চুয়াল ফাংশন নেই। আপনি যদি কোনও প্রকার থেকে উদ্ভূত হন তবে আপনাকে তার সদস্য ফাংশনগুলি বলা যেতে পারে এই বিষয়টি মোকাবেলা করতে হবে!
এখানে বেশিরভাগ উত্তর স্লাইসিংয়ের সাথে আসল সমস্যাটি কী তা ব্যাখ্যা করতে ব্যর্থ হয়। এগুলি কেবল কাটা কাটানোর সৌম্য মামলাগুলি ব্যাখ্যা করে, বিশ্বাসঘাতকরা নয়। অন্যান্য উত্তরগুলির মতো, ধরে নিন যে আপনি দুটি শ্রেণী নিয়ে কাজ করছেন 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
।
derived
মান মান প্রত্যাশী কোডকে দেওয়া যেতে পারে base
, বা কোনও উত্পন্ন রেফারেন্স বেস রেফারেন্স হিসাবে ব্যবহার করা যেতে পারে। আমি একটি টাইপ সিস্টেমের সাথে একটি ভাষা দেখতে চাই যা উভয় ধারণাকে পৃথকভাবে সম্বোধন করে। অনেকগুলি ক্ষেত্রে রয়েছে যেখানে উত্পন্ন রেফারেন্সটি বেস রেফারেন্সের পরিবর্তে পরিবর্তনযোগ্য হওয়া উচিত, তবে উত্পন্ন উদাহরণগুলি বেসের জন্য পরিবর্তিতযোগ্য হওয়া উচিত নয়; এমন অনেকগুলি ঘটনা রয়েছে যেখানে দৃষ্টান্তগুলি রূপান্তরযোগ্য হওয়া উচিত তবে রেফারেন্সগুলির বিকল্প হওয়া উচিত নয়।
আপনার যদি একটি বেস ক্লাস 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
হারিয়ে গেছে)।wantAnA
(এর নাম অনুসারে!) একটি চায় A
, তবে এটি যা পায় it এবং একটি উদাহরণ A
, ইচ্ছা, আহ মত আচরণ করে A
। কীভাবে অবাক হয়?
derived
টাইপ করে A
। অন্তর্নিহিত ingালাই সর্বদা সি ++ তে অপ্রত্যাশিত আচরণের উত্স, কারণ স্থানীয়ভাবে কোডটি স্থান পেয়েছে এমন কোডটি দেখে বোঝা প্রায়শই শক্ত।
এগুলি সব ভাল উত্তর। রেফারেন্স অনুসারে মান দ্বারা বনাম বস্তুগুলি পাস করার সময় আমি একটি কার্যকরকরণের উদাহরণটি যুক্ত করতে চাই:
#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'
"সি ++ স্লাইসিং" এর জন্য গুগলের তৃতীয় ম্যাচটি আমাকে এই উইকিপিডিয়া নিবন্ধটি http://en.wikedia.org/wiki/Object_slicing এবং এটি দেয় (উত্তপ্ত, তবে প্রথম কয়েকটি পোস্ট সমস্যার সংজ্ঞা দেয়): http://bytes.com/ ফোরাম / thread163565.html
সুতরাং আপনি যখন সুপার ক্লাসে একটি সাবক্লাসের একটি বিষয় বরাদ্দ করেন। সুপারক্লাস সাবক্লাসে অতিরিক্ত তথ্যের কিছুই জানে না, এবং এটি সঞ্চয় করার মতো জায়গাও পায় নি, সুতরাং অতিরিক্ত তথ্য "কাটা কাটা" হয়ে যায়।
যদি এই লিঙ্কগুলি কোনও "ভাল উত্তর" দেওয়ার জন্য পর্যাপ্ত তথ্য না দেয় তবে দয়া করে আপনার আরও কী সন্ধান করছেন তা আমাদের জানানোর জন্য আপনার প্রশ্নটি সম্পাদনা করুন।
টুকরো টুকরো করার সমস্যাটি গুরুতর কারণ এটি মেমোরির দুর্নীতির ফলে তৈরি হতে পারে এবং কোনও প্রোগ্রাম এতে ক্ষতিগ্রস্থ হয় না তার গ্যারান্টি দেওয়া খুব কঠিন। ভাষা থেকে এটি ডিজাইনের জন্য, উত্তরাধিকারকে সমর্থন করে এমন ক্লাসগুলি কেবলমাত্র রেফারেন্সের মাধ্যমে (মান দ্বারা নয়) অ্যাক্সেসযোগ্য। ডি প্রোগ্রামিং ভাষার এই সম্পত্তি রয়েছে।
A বিভাগটি বিবেচনা করুন এবং এ থেকে উত্পন্ন ক্লাস বিটি এ এর অংশের একটি পয়েন্টার পি, এবং একটি খ উদাহরণ রয়েছে যা বি এর অতিরিক্ত ডেটাতে পয়েন্ট করে মেমরি দুর্নীতি হতে পারে। তারপরে, অতিরিক্ত তথ্য বিচ্ছিন্ন হয়ে গেলে, পি আবর্জনার দিকে নির্দেশ করছে।
Derived
এটি স্পষ্টভাবে রূপান্তরিত Base
।) এটি স্পষ্টতই উন্মুক্ত-বন্ধ নীতিটির বিপরীতে এবং একটি বড় রক্ষণাবেক্ষণের বোঝা।
সি ++ তে, একটি উত্পন্ন শ্রেণি অবজেক্টকে বেস শ্রেণীর বস্তুকে বরাদ্দ করা যেতে পারে, তবে অন্য উপায়টি সম্ভব নয়।
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
}
অবজেক্ট স্লাইসিংয়ের ঘটনা ঘটে যখন কোনও উত্পন্ন শ্রেণীর অবজেক্টটি একটি বেস শ্রেণীর অবজেক্টকে অর্পণ করা হয়, একটি উত্পন্ন শ্রেণীর অবজেক্টের অতিরিক্ত বৈশিষ্ট্যগুলি বেস শ্রেণীর অবজেক্টটি গঠনের জন্য কেটে ফেলা হয়।
সি ++ এ টুকরো টুকরো টুকরো টুকরো সমস্যা এর বস্তুর মান শব্দার্থতত্ত্ব থেকে উদ্ভূত, যা বেশিরভাগ সি স্ট্রকের সাথে সামঞ্জস্যতার কারণে থেকে যায়। বেশিরভাগ অন্যান্য ভাষায় যে বস্তুগুলি ব্যবহার করে, অর্থাৎ বস্তুগুলিকে সর্বদা রেফারেন্সের মাধ্যমে অতিক্রম করা হয় তার মধ্যে পাওয়া "স্বাভাবিক" অবজেক্ট আচরণ অর্জনের জন্য আপনাকে সুস্পষ্ট রেফারেন্স বা পয়েন্টার সিনট্যাক্স ব্যবহার করতে হবে।
সংক্ষিপ্ত উত্তরগুলি হ'ল আপনি মানটিকে ভিত্তি করে কোনও অবৈধ বস্তুকে একটি উত্পন্ন বস্তু বরাদ্দ করে বস্তুটি টুকরো টুকরো করেন , অর্থাত্ বাকী অবজেক্টটি প্রাপ্ত হওয়া অবজেক্টের একটি অংশ মাত্র। মান শব্দার্থ সংরক্ষণের জন্য, স্লাইসিং একটি যুক্তিসঙ্গত আচরণ এবং এর অপেক্ষাকৃত বিরল ব্যবহার রয়েছে, যা বেশিরভাগ অন্যান্য ভাষায় নেই। কিছু লোক এটিকে সি ++ এর বৈশিষ্ট্য হিসাবে বিবেচনা করে, আবার অনেকে এটিকে C ++ এর অন্যতম বাতুলতা / অপব্যবহার বলে বিবেচনা করে।
struct
, সামঞ্জস্য, অথবা অন্য অ-ইন্দ্রিয় কোন র্যান্ডম গলি যাজক তোমাকে বলেছিলাম।
Base
অবশ্যই sizeof(Base)
মেমরির হুবহু বাইট নিতে হবে , সম্ভবত "অ্যাসাইনমেন্ট" (অন-স্ট্যাক-অনুলিপি) ) উদ্ভূত শ্রেণীর সদস্যদের অনুলিপি করবে না, তাদের অফসেটগুলি আকারের বাইরে। "ডেটা হারাতে" এড়াতে, কেবল অন্য কারোর মতো পয়েন্টার ব্যবহার করুন, যেহেতু পয়েন্টার মেমরিটি স্থান এবং আকারে স্থির থাকে, তবে স্ট্যাকটি খুব স্বচ্ছল
সুতরাং ... প্রাপ্ত তথ্য হারানো কেন খারাপ? ... কারণ উত্পন্ন শ্রেণীর লেখক এমন উপস্থাপনা পরিবর্তন করতে পারেন যে অতিরিক্ত তথ্য কাটলে বস্তুর দ্বারা প্রতিনিধিত্ব করা মানকে পরিবর্তন করে। যদি উদ্ভূত শ্রেণীর কোনও উপস্থাপনা ক্যাশে ব্যবহৃত হয় যা নির্দিষ্ট ক্রিয়াকলাপের জন্য আরও দক্ষ, তবে বেস উপস্থাপনায় ফিরে যেতে ব্যয়বহুল হয় তবে এটি ঘটতে পারে।
এছাড়াও ভেবেছিল কেউ কাটা কাটা এড়াতে আপনার কী করা উচিত তাও উল্লেখ করা উচিত ... সি ++ কোডিং স্ট্যান্ডার্ডস, 101 টি বিধি নির্দেশিকা এবং সেরা অনুশীলনের একটি অনুলিপি পান। স্লাইসিংয়ের সাথে ডিলিং হচ্ছে # 54।
এটি পুরোপুরি ইস্যুটি মোকাবেলা করার জন্য কিছুটা পরিশীলিত প্যাটার্নের পরামর্শ দেয়: একটি সুরক্ষিত অনুলিপি নির্মাণকারী, একটি সুরক্ষিত খাঁটি ভার্চুয়াল ডক্লোন এবং একটি সার্বজনীন ক্লোন রয়েছে যা আপনাকে জানায় যে কোনও (আরও) প্রাপ্ত শ্রেণি সঠিকভাবে ডক্লোন প্রয়োগ করতে ব্যর্থ হয়েছে কিনা তা আপনাকে বলবে। (ক্লোন পদ্ধতিটি বহুগুণিত বস্তুর যথাযথ গভীর অনুলিপি তৈরি করে))
আপনি অনুলিপি বেসটি অনুলিপিতে অনুলিপি করতে পারেন যা এটি পছন্দসই হলে স্পষ্টভাবে কাটানোর জন্য অনুমতি দেয়।
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;
এই ক্ষেত্রে, পিটিআরডি (বংশধর শ্রেণীর অবজেক্ট) দ্বারা চিহ্নিত গতিশীল ভেরিয়েবলের ডেটা সদস্য বা সদস্য ফাংশনগুলির কোনওটিই হারাবে না। এছাড়াও, যদি আপনাকে ফাংশনগুলি ব্যবহার করতে হয় তবে ফাংশনটি ভার্চুয়াল ফাংশন হতে হবে।
dog
শ্রেণীর অংশ নয় Pet
( breed
ডেটা মেম্বার) ভেরিয়েবলে অনুলিপি করে না pet
? কোডটি কেবল Pet
ডেটা সদস্যদের মধ্যেই আগ্রহী - দৃশ্যত। কাঁচকাটা অবশ্যই যদি এটি অযাচিত হয় তবে একটি "সমস্যা", তবে আমি এখানে এটি দেখতে পাচ্ছি না।
((Dog *)ptrP)
" আমি ব্যবহার করার পরামর্শ দিচ্ছিstatic_cast<Dog*>(ptrP)
Dog::breed
করা কোনওভাবেই স্লিকিংয়ের সাথে সম্পর্কিত কোনও ত্রুটি নয়?
আমার কাছে মনে হয়, আপনার নিজের ক্লাস এবং প্রোগ্রামটি খারাপভাবে নকশাকৃত / নকশাকৃত হওয়ার পরে কাটা কাটা এত সমস্যা নয়।
আমি যদি কোনও উপক্লাস অবজেক্টকে কোনও পদ্ধতির কাছে প্যারামিটার হিসাবে পাস করি, যা সুপারক্লাস টাইপের একটি প্যারামিটার নেয় তবে আমার অবশ্যই এটি সম্পর্কে সচেতন হওয়া উচিত এবং অভ্যন্তরীণভাবে জানতে হবে, তথাকথিত পদ্ধতিটি কেবল সুপারক্লাস (ওরফে বেসক্লাস) অবজেক্টের সাথে কাজ করবে।
আমার কাছে কেবল অযৌক্তিক প্রত্যাশা বলে মনে হচ্ছে যে সাবক্লাস সরবরাহ করা যেখানে বেসক্লাসের অনুরোধ করা হয়েছে, কোনও উপক্লাসের নির্দিষ্ট ফলাফল হতে পারে, স্লাইসিংয়ের সমস্যা হতে পারে। পদ্ধতিটির ব্যবহারে এটির দুর্বল নকশা বা একটি নিম্ন উপক্লাস বাস্তবায়ন। আমি সাধারণত এটি সাফল্য বা পারফরম্যান্স লাভের পক্ষে ভাল ওওপি ডিজাইনের ত্যাগের ফলাফল অনুমান করছি।
ঠিক আছে, আমি বস্তুর স্লাইসিংয়ের ব্যাখ্যা দিয়ে অনেকগুলি পোস্ট পড়ার পরে এটিকে চেষ্টা করব তবে কীভাবে সমস্যাযুক্ত হয় তা নয়।
মেমরির দুর্নীতির পরিণতি ঘটাতে পারে এমন দুষ্ট দৃশ্যটি নিম্নলিখিত:
টুকরো টুকরো করার অর্থ হ'ল সাবক্লাস দ্বারা যুক্ত করা ডেটা যখন সাবক্লাসের কোনও অবজেক্টকে মান দ্বারা পাস করা হয় বা কোনও বেস ক্লাসের অবজেক্টের প্রত্যাশা করে এমন কোনও ফাংশন থেকে ফেরত দেওয়া হয় তখন তা বাতিল করা হয়।
ব্যাখ্যা: নিম্নলিখিত শ্রেণীর ঘোষণা বিবেচনা করুন:
class baseclass
{
...
baseclass & operator =(const baseclass&);
baseclass(const baseclass&);
}
void function( )
{
baseclass obj1=m;
obj1=m;
}
বেসক্লাসের অনুলিপি ফাংশনগুলি যেমন উত্পন্ন সম্পর্কে কিছুই জানে না কেবলমাত্র প্রাপ্ত ব্যয়ের অংশটি অনুলিপি করা হয়। এটি সাধারণত কাটা হিসাবে উল্লেখ করা হয়।
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;
}
যখন একটি উত্পন্ন শ্রেণি অবজেক্টটি একটি বেস শ্রেণীর অবজেক্টকে বরাদ্দ করা হয়, তখন একটি উত্পন্ন শ্রেণীর অবজেক্টের অতিরিক্ত বৈশিষ্ট্যগুলি বিচ্ছিন্ন করে দেওয়া হয় (বাতিল করা হবে) বেস শ্রেণীর অবজেক্টটি গঠন করে।
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
}
যখন একটি ডেরিভেড ক্লাস অবজেক্ট বেস ক্লাস অবজেক্টকে অর্পণ করা হয়, তখন ড্রেভড ক্লাস অবজেক্টের সমস্ত সদস্য বেস ক্লাসে উপস্থিত না থাকা সদস্য ব্যতীত বেস ক্লাস অবজেক্টে অনুলিপি করা হয়। এই সদস্যগুলি সংকলক দ্বারা বিচ্ছিন্ন করা হয়। একে অবজেক্ট স্লাইসিং বলা হয়।
এখানে একটি উদাহরণ:
#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'
আমি স্লাইসিং সমস্যাটি পেরিয়ে সরাসরি ততক্ষণে এখানে পৌঁছেছি। সুতরাং আমাকে এই আমার দুটি সেন্ট যোগ করুন।
আসুন "প্রোডাকশন কোড" (বা এমন কিছু আসে যা কিছু ধরণের কাছাকাছি আসে) থেকে নেওয়া যাক:
ধরা যাক আমাদের এমন কিছু আছে যা ক্রিয়া প্রেরণ করে। উদাহরণস্বরূপ একটি নিয়ন্ত্রণ কেন্দ্র ইউআই।
এই ইউআই-তে বর্তমানে প্রেরণে সক্ষম এমন জিনিসগুলির একটি তালিকা পাওয়া দরকার। সুতরাং আমরা প্রেরণ-তথ্য ধারণ করে এমন একটি শ্রেণির সংজ্ঞা দিই। এটি কল করুন 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
এস সম্পর্কে কিছু কথাবার্তা বলার সময় সত্যিই জিনিসগুলি কল্পনা করতে পারে না ।