ইন্টারফেসের প্রতিনিধিত্ব করে এমন একটি ক্লাস কীভাবে সেটআপ করব? এটি কি কেবল একটি বিমূর্ত বেস শ্রেণি?
ইন্টারফেসের প্রতিনিধিত্ব করে এমন একটি ক্লাস কীভাবে সেটআপ করব? এটি কি কেবল একটি বিমূর্ত বেস শ্রেণি?
উত্তর:
Bradtgmurray দ্বারা উত্তরের প্রসারিত করতে , আপনি ভার্চুয়াল ডেস্ট্রাক্টর যুক্ত করে আপনার ইন্টারফেসের খাঁটি ভার্চুয়াল পদ্ধতি তালিকায় একটি ব্যতিক্রম করতে চাইতে পারেন। এটি আপনাকে কংক্রিটের উত্পন্ন ক্লাসটি প্রকাশ না করেই অন্য দলের কাছে পয়েন্টার মালিকানা পাস করতে দেয়। ডেস্ট্রাক্টরকে কিছু করতে হবে না, কারণ ইন্টারফেসের কোনও কংক্রিট সদস্য নেই। কোনও ফাংশনটিকে ভার্চুয়াল এবং ইনলাইন উভয় হিসাবে সংজ্ঞায়িত করার জন্য এটি পরস্পরবিরোধী বলে মনে হতে পারে তবে আমার বিশ্বাস করুন - এটি নয়।
class IDemo
{
public:
virtual ~IDemo() {}
virtual void OverrideMe() = 0;
};
class Parent
{
public:
virtual ~Parent();
};
class Child : public Parent, public IDemo
{
public:
virtual void OverrideMe()
{
//do stuff
}
};
ভার্চুয়াল ডেস্ট্রাক্টরের জন্য আপনাকে কোনও দেহ অন্তর্ভুক্ত করতে হবে না - এটি বেরিয়ে আসে কিছু সংকলককে খালি ডেস্ট্রাক্টরকে অনুকূল করতে সমস্যা হয় এবং আপনি ডিফল্টটি ব্যবহার করে আরও ভাল হন।
=0
দেহ সহ খাঁটি ভার্চুয়াল ( ) ডেস্ট্রাক্টরকে সংজ্ঞায়িত করা । এখানে সুবিধাটি হ'ল সংকলকটি তাত্ত্বিকভাবে দেখতে পারেন যে এখন ভেটেবলের কোনও বৈধ সদস্য নেই, এবং এটি পুরোপুরি ফেলে দিতে পারেন। একটি বডি সহ ভার্চুয়াল ডেস্ট্রাক্টরের সাথে, বলে যে বিন্যাসকারীকে (ভার্চুয়াল) বলা যেতে পারে যেমন this
পয়েন্টারের মাধ্যমে নির্মাণের মাঝখানে (যখন নির্মিত বস্তুটি এখনও Parent
টাইপ থাকে), এবং তাই সংকলককে একটি বৈধ vtable সরবরাহ করতে হবে। সুতরাং আপনি যদি this
নির্মাণের সময় স্পষ্টভাবে ভার্চুয়াল ডেস্ট্রাক্টরদের কল না করেন :) আপনি কোড আকারে সঞ্চয় করতে পারবেন।
override
সংকলন-সময় আর্গুমেন্ট এবং রিটার্ন মান ধরণের পরীক্ষার জন্য কীওয়ার্ডটি নির্দিষ্ট করতে পারেন । উদাহরণস্বরূপ, সন্তানের ঘোষণায়virtual void OverrideMe() override;
খাঁটি ভার্চুয়াল পদ্ধতিতে একটি শ্রেণি তৈরি করুন। অন্য শ্রেণি তৈরি করে ইন্টারফেসটি ব্যবহার করুন যা সেই ভার্চুয়াল পদ্ধতিগুলিকে ওভাররাইড করে।
খাঁটি ভার্চুয়াল পদ্ধতিটি একটি শ্রেণি পদ্ধতি যা ভার্চুয়াল হিসাবে সংজ্ঞায়িত হয় এবং 0 তে নির্ধারিত হয়।
class IDemo
{
public:
virtual ~IDemo() {}
virtual void OverrideMe() = 0;
};
class Child : public IDemo
{
public:
virtual void OverrideMe()
{
//do stuff
}
};
override
C ++ 11
সি # / জাভাতে বিমূর্ত বেস ক্লাস ছাড়াও আপনার একটি বিশেষ ইন্টারফেস টাইপ-বিভাগের পুরো কারণ হ'ল সি # / জাভা একাধিক উত্তরাধিকার সমর্থন করে না।
সি ++ একাধিক উত্তরাধিকারকে সমর্থন করে এবং তাই একটি বিশেষ ধরণের প্রয়োজন হয় না। নন-অ্যাবস্ট্রাক্ট (খাঁটি ভার্চুয়াল) পদ্ধতিবিহীন একটি বিমূর্ত বেস শ্রেণিটি কার্যত সি # / জাভা ইন্টারফেসের সমতুল্য।
Thread
উদাহরণ হয়ে উঠুক । একাধিক উত্তরাধিকার খারাপ নকশা পাশাপাশি রচনা হতে পারে। এটি সব ক্ষেত্রে নির্ভর করে।
সি ++ তে প্রতি সেফের "ইন্টারফেস" ধারণা নেই। আফাইক, একাধিক উত্তরাধিকারের অভাবে কাজ করার জন্য প্রথমে জাভাতে ইন্টারফেস চালু করা হয়েছিল। এই ধারণাটি বেশ কার্যকর হিসাবে দেখা গেছে, এবং একই প্রভাবটি একটি বিমূর্ত বেস বর্গ ব্যবহার করে সি ++ এ অর্জন করা যেতে পারে।
অ্যাবস্ট্রাক্ট বেস ক্লাসটি এমন একটি ক্লাস যেখানে কমপক্ষে একটি সদস্য ফাংশন (জাভা লিঙ্গোর পদ্ধতি) নীচের সিনট্যাক্স ব্যবহার করে ঘোষিত একটি খাঁটি ভার্চুয়াল ফাংশন:
class A
{
virtual void foo() = 0;
};
একটি বিমূর্ত বেস শ্রেণি তাত্ক্ষণিকভাবে চালু করা যায় না, অর্থাত আপনি ক্লাস এ এর কোনও বিষয় ঘোষণা করতে পারবেন না আপনি কেবল এ থেকে ক্লাস অর্জন করতে পারেন, তবে যে কোনও উদ্ভূত শ্রেণি যা বাস্তবায়ন প্রদান করে না foo()
তাও বিমূর্ত হবে। বিমূর্ত হওয়া বন্ধ করার জন্য, একটি উত্পন্ন শ্রেণিকে অবশ্যই উত্তরাধিকার সূত্রে প্রাপ্ত সমস্ত খাঁটি ভার্চুয়াল ফাংশনগুলির জন্য বাস্তবায়ন সরবরাহ করতে হবে।
মনে রাখবেন যে একটি বিমূর্ত বেস শ্রেণি ইন্টারফেসের চেয়ে বেশি হতে পারে, কারণ এতে ডেটা সদস্য এবং সদস্য ফাংশন থাকতে পারে যা খাঁটি ভার্চুয়াল নয়। একটি ইন্টারফেসের সমতুল্য হ'ল কেবল বিশুদ্ধ ভার্চুয়াল ফাংশন সহ কোনও ডেটা ছাড়াই একটি বিমূর্ত বেস শ্রেণি হবে।
এবং, মার্ক র্যানসোম ইঙ্গিত অনুসারে, একটি বিমূর্ত বেস শ্রেণীর ক্ষেত্রে কোনও বেস ক্লাসের মতো ভার্চুয়াল ডেস্ট্রাক্টর সরবরাহ করা উচিত।
আমি যতদূর পরীক্ষা করতে পারি, ভার্চুয়াল ডেস্ট্রাক্টর যুক্ত করা খুব গুরুত্বপূর্ণ। আমি এর সাথে নির্মিত new
এবং ধ্বংস হওয়া বস্তুগুলি ব্যবহার করছি delete
।
আপনি যদি ইন্টারফেসে ভার্চুয়াল ডেস্ট্রাক্টর যোগ না করেন তবে উত্তরাধিকারসূত্রে প্রাপ্ত শ্রেণীর ডেস্ট্রাক্টরকে ডাকা হয় না।
class IBase {
public:
virtual ~IBase() {}; // destructor, use it to call destructor of the inherit classes
virtual void Describe() = 0; // pure virtual method
};
class Tester : public IBase {
public:
Tester(std::string name);
virtual ~Tester();
virtual void Describe();
private:
std::string privatename;
};
Tester::Tester(std::string name) {
std::cout << "Tester constructor" << std::endl;
this->privatename = name;
}
Tester::~Tester() {
std::cout << "Tester destructor" << std::endl;
}
void Tester::Describe() {
std::cout << "I'm Tester [" << this->privatename << "]" << std::endl;
}
void descriptor(IBase * obj) {
obj->Describe();
}
int main(int argc, char** argv) {
std::cout << std::endl << "Tester Testing..." << std::endl;
Tester * obj1 = new Tester("Declared with Tester");
descriptor(obj1);
delete obj1;
std::cout << std::endl << "IBase Testing..." << std::endl;
IBase * obj2 = new Tester("Declared with IBase");
descriptor(obj2);
delete obj2;
// this is a bad usage of the object since it is created with "new" but there are no "delete"
std::cout << std::endl << "Tester not defined..." << std::endl;
descriptor(new Tester("Not defined"));
return 0;
}
আপনি যদি পূর্ববর্তী কোডটি চালনা করে চালিয়ে যান তবে আপনি virtual ~IBase() {};
দেখতে পাবেন যে বিনষ্টকারীকে Tester::~Tester()
কখনই ডাকা হয় না।
আমার উত্তরটি মূলত অন্যদের মতই তবে আমার মনে হয় আরও দুটি গুরুত্বপূর্ণ জিনিস করা আছে:
আপনার ইন্টারফেসে ভার্চুয়াল ডেস্ট্রাক্টর ঘোষণা করুন বা যদি কেউ কোনও ধরণের অবজেক্ট মুছতে চেষ্টা করে তবে অপরিজ্ঞাত আচরণগুলি এড়াতে একটি সুরক্ষিত অ-ভার্চুয়ালকে তৈরি করুন IDemo
।
একাধিক উত্তরাধিকার নিয়ে সমস্যা এড়াতে ভার্চুয়াল উত্তরাধিকার ব্যবহার করুন। (যখন আমরা ইন্টারফেসগুলি ব্যবহার করি তখন প্রায়শই একাধিক উত্তরাধিকার থাকে))
এবং অন্যান্য উত্তরের মতো:
অন্য শ্রেণি তৈরি করে ইন্টারফেসটি ব্যবহার করুন যা সেই ভার্চুয়াল পদ্ধতিগুলিকে ওভাররাইড করে।
class IDemo
{
public:
virtual void OverrideMe() = 0;
virtual ~IDemo() {}
}
অথবা
class IDemo
{
public:
virtual void OverrideMe() = 0;
protected:
~IDemo() {}
}
এবং
class Child : virtual public IDemo
{
public:
virtual void OverrideMe()
{
//do stuff
}
}
সি ++ 11 এ আপনি সহজেই উত্তরাধিকার সম্পূর্ণ এড়াতে পারবেন:
struct Interface {
explicit Interface(SomeType& other)
: foo([=](){ return other.my_foo(); }),
bar([=](){ return other.my_bar(); }), /*...*/ {}
explicit Interface(SomeOtherType& other)
: foo([=](){ return other.some_foo(); }),
bar([=](){ return other.some_bar(); }), /*...*/ {}
// you can add more types here...
// or use a generic constructor:
template<class T>
explicit Interface(T& other)
: foo([=](){ return other.foo(); }),
bar([=](){ return other.bar(); }), /*...*/ {}
const std::function<void(std::string)> foo;
const std::function<void(std::string)> bar;
// ...
};
এই ক্ষেত্রে, একটি ইন্টারফেসের রেফারেন্স সিমানটিকস রয়েছে, অর্থাত্ আপনাকে নিশ্চিত করতে হবে যে অবজেক্টটি ইন্টারফেসটিকে আউটলাইভ করে (এটি মূল্য শব্দার্থক দ্বারা ইন্টারফেস করাও সম্ভব)।
এই ধরণের ইন্টারফেসগুলির উপকারিতা এবং বিধিগুলি রয়েছে:
অবশেষে, জটিল সফ্টওয়্যার ডিজাইনের সমস্ত উত্তরণের মূল হ'ল উত্তরাধিকার। ইন শন পিতামাতাদের মূল্য শব্দ এবং ধারণা ভিত্তিক পলিমরফিজ্ম (অত্যন্ত বাঞ্ছনীয় এই প্রযুক্তিটি ভালো সংস্করণ আছে ব্যাখ্যা করা হয়) নিম্নলিখিত ক্ষেত্রে চর্চিত হয়:
বলুন আমার একটি অ্যাপ্লিকেশন রয়েছে যাতে আমি MyShape
ইন্টারফেসটি ব্যবহার করে বহু আকারে আমার আকারগুলি ব্যবহার করি :
struct MyShape { virtual void my_draw() = 0; };
struct Circle : MyShape { void my_draw() { /* ... */ } };
// more shapes: e.g. triangle
আপনার অ্যাপ্লিকেশনটিতে, আপনি YourShape
ইন্টারফেসটি ব্যবহার করে বিভিন্ন আকারের সাথে একই কাজটি করেন :
struct YourShape { virtual void your_draw() = 0; };
struct Square : YourShape { void your_draw() { /* ... */ } };
/// some more shapes here...
এখন বলুন যে আমি আপনার অ্যাপ্লিকেশনটিতে বিকাশ করেছি এমন কিছু আকার ব্যবহার করতে চাই। ধারণামূলকভাবে, আমাদের আকারগুলির একই ইন্টারফেস রয়েছে, তবে আমার আকারগুলি আপনার প্রয়োগে কাজ করতে আপনাকে আমার আকারগুলি নিম্নরূপে প্রসারিত করতে হবে:
struct Circle : MyShape, YourShape {
void my_draw() { /*stays the same*/ };
void your_draw() { my_draw(); }
};
প্রথমত, আমার আকারগুলি সংশোধন করা মোটেও সম্ভব নয়। তদ্ব্যতীত, একাধিক উত্তরাধিকার স্প্যাগেটি কোডের পথে নিয়ে যায় (কল্পনা করুন যে কোনও তৃতীয় প্রকল্প এসেছে যার মধ্যে TheirShape
ইন্টারফেসটি ব্যবহার করা হচ্ছে ... তারা যদি তাদের ড্র ফাংশনও বলে তবে কী ঘটে my_draw
?)
আপডেট: অ-উত্তরাধিকার ভিত্তিক পলিমারফিজম সম্পর্কে কয়েকটি নতুন উল্লেখ রয়েছে:
Circle
শ্রেণি একটি দুর্বল নকশা। এই Adapter
জাতীয় ক্ষেত্রে আপনার প্যাটার্ন ব্যবহার করা উচিত । দুঃখিত যদি এটি কিছুটা কঠোর মনে হয় তবে Qt
উত্তরাধিকার সম্পর্কে রায় দেওয়ার আগে কিছু বাস্তব জীবনের লাইব্রেরি ব্যবহার করার চেষ্টা করুন । উত্তরাধিকার জীবনকে অনেক সহজ করে তোলে।
Adapter
প্যাটার্নটি ব্যবহার করে আপনি সার্কেল ফিক্স করার একটি উদাহরণ (হয়ত আদর্শে) দিতে পারেন ? আমি এর সুবিধাগুলি দেখতে আগ্রহী।
Square
যে ইতিমধ্যে সেখানে নেই? দূরদর্শন? এ কারণেই এটি বাস্তবতা থেকে বিচ্ছিন্ন। এবং বাস্তবে আপনি যদি "মাই শেপ" লাইব্রেরির উপর নির্ভর করতে চান তবে আপনি প্রথম থেকেই তার ইন্টারফেসে গ্রহণ করতে পারেন। আকারের উদাহরণে অনেক ননসেন্স রয়েছে (যার একটিতে আপনার দুটি Circle
স্ট্রাক্ট রয়েছে), তবে অ্যাডাপ্টারের মতো দেখতে কিছু হবে -> আদর্শ one.com/UogjWk
উপরে সমস্ত ভাল উত্তর। আপনার অতিরিক্ত একটি জিনিস মনে রাখা উচিত - আপনার খাঁটি ভার্চুয়াল ডেস্ট্রাক্টরও থাকতে পারে। পার্থক্যটি হ'ল আপনার এখনও এটি প্রয়োগ করা দরকার।
বিভ্রান্ত?
--- header file ----
class foo {
public:
foo() {;}
virtual ~foo() = 0;
virtual bool overrideMe() {return false;}
};
---- source ----
foo::~foo()
{
}
আপনি যেটি করতে চাইছেন তার প্রধান কারণ হ'ল যদি আপনি আমার মতো ইন্টারফেসের পদ্ধতিগুলি সরবরাহ করতে চান তবে সেগুলি overচ্ছিকভাবে ওভাররাইড করা।
শ্রেণিটিকে ইন্টারফেস বানাতে একটি খাঁটি ভার্চুয়াল পদ্ধতি প্রয়োজন, তবে আপনার সমস্ত ভার্চুয়াল পদ্ধতিতে ডিফল্ট প্রয়োগ রয়েছে, তাই খাঁটি ভার্চুয়াল তৈরির একমাত্র পদ্ধতিটি হ'ল ডেস্ট্রাক্টর।
উদ্ভূত শ্রেণিতে একজন ডেস্ট্রাক্টরকে পুনর্নির্মাণ করা মোটেও বড় বিষয় নয় - আমি সর্বদা আমার উদ্ভূত ক্লাসগুলিতে একজন ডেস্ট্রাক্টর, ভার্চুয়াল বা না-কে পুনরায় প্রতিস্থাপন করি।
আপনি যদি মাইক্রোসফ্টের সি ++ সংকলক ব্যবহার করেন তবে আপনি নিম্নলিখিতগুলি করতে পারেন:
struct __declspec(novtable) IFoo
{
virtual void Bar() = 0;
};
class Child : public IFoo
{
public:
virtual void Bar() override { /* Do Something */ }
}
আমি এই পদ্ধতির পছন্দ করি কারণ এটির ফলে অনেকগুলি ছোট ইন্টারফেস কোড আসে এবং উত্পন্ন কোডের আকার উল্লেখযোগ্যভাবে ছোট হতে পারে। অবিশ্বাস্য টেবিলের ব্যবহার সেই শ্রেণীর vtable পয়েন্টারের সমস্ত রেফারেন্স সরিয়ে দেয়, তাই আপনি কখনই সরাসরি তা ইনস্ট্যান্ট করতে পারবেন না। ডকুমেন্টেশন এখানে দেখুন - novtable ।
novtable
স্ট্যান্ডার্ডের চেয়ে বেশি ব্যবহার করেছেন তা আমি বেশ দেখতে পাই নাvirtual void Bar() = 0;
= 0;
যুক্ত করেছি যা আমি হারিয়েছি তা লক্ষ্য করেছি)। ডকুমেন্টেশনটি বুঝতে না পারলে তা পড়ুন।
= 0;
এবং ধরে নিয়েছি এটি ঠিক একই কাজ করার একটি অ-মানক উপায়।
সেখানে যা লেখা আছে তার সাথে সামান্য সংযোজন:
প্রথমত, নিশ্চিত করুন যে আপনার ধ্বংসকারীও খাঁটি ভার্চুয়াল
দ্বিতীয়ত, আপনি প্রয়োগ করার সময় আপনি কেবলমাত্র ভাল ব্যবস্থার জন্য কার্যত (সাধারণত না বরং) উত্তরাধিকার সূচনা করতে পারেন।
আপনি এনভিআই (নন ভার্চুয়াল ইন্টারফেস প্যাটার্ন) এর সাথে বাস্তবায়িত চুক্তি ক্লাসগুলিও বিবেচনা করতে পারেন। এই ক্ষেত্রে:
struct Contract1 : boost::noncopyable
{
virtual ~Contract1();
void f(Parameters p) {
assert(checkFPreconditions(p)&&"Contract1::f, pre-condition failure");
// + class invariants.
do_f(p);
// Check post-conditions + class invariants.
}
private:
virtual void do_f(Parameters p) = 0;
};
...
class Concrete : public Contract1, public Contract2
{
private:
virtual void do_f(Parameters p); // From contract 1.
virtual void do_g(Parameters p); // From contract 2.
};
আমি সি ++ বিকাশে এখনও নতুন। আমি ভিজ্যুয়াল স্টুডিও (ভিএস) দিয়ে শুরু করেছি।
তবুও, __interface
ভিএস (। নেট) তে কেউ উল্লেখ করেছেন বলে মনে হয় না । আমি না খুব নিশ্চিত যদি এই একটি ভাল উপায় হল একটি ইন্টারফেস ঘোষণা হয়। তবে মনে হয় এটি একটি অতিরিক্ত প্রয়োগকারী সরবরাহ করে ( নথিতে উল্লিখিত )। এটি আপনাকে স্বতঃস্ফূর্তভাবে নির্দিষ্ট করতে হবে না virtual TYPE Method() = 0;
, যেহেতু এটি স্বয়ংক্রিয়ভাবে রূপান্তরিত হবে।
__interface IMyInterface {
HRESULT CommitX();
HRESULT get_X(BSTR* pbstrName);
};
তবে আমি এটি ব্যবহার করি না কারণ আমি ক্রস প্ল্যাটফর্ম সংকলন সামঞ্জস্যতা নিয়ে উদ্বিগ্ন, কারণ এটি কেবলমাত্র নেট। এর অধীনে উপলব্ধ।
কারও কাছে এটি সম্পর্কে আকর্ষণীয় কিছু থাকলে দয়া করে শেয়ার করুন। :-)
ধন্যবাদ।
যদিও এটি সত্য যে virtual
কোনও ইন্টারফেসটি সংজ্ঞায়িত করার জন্য ডি-ফ্যাক্টো স্ট্যান্ডার্ড, আসুন আমরা ক্লাসিক সি-জাতীয় প্যাটার্নটি ভুলে যাব না, যা সি ++ তে একটি নির্মাণকারীর সাথে আসে:
struct IButton
{
void (*click)(); // might be std::function(void()) if you prefer
IButton( void (*click_)() )
: click(click_)
{
}
};
// call as:
// (button.*click)();
এটির সুবিধাটি রয়েছে যে আপনি নিজের ক্লাসটি আবার তৈরি না করেই ইভেন্ট রানটাইমটিকে পুনরায় বাঁধতে পারবেন (যেমন সি ++ তে বহুবর্ষীয় ধরণের পরিবর্তনের জন্য একটি সিনট্যাক্স নেই, এটি গিরগিটি শ্রেণীর জন্য কার্যকর)।
পরামর্শ:
click
আপনার বংশধরের কনস্ট্রাক্টর পূরণ করুন ।protected
সদস্য হিসাবে ফাংশন পয়েন্টার থাকতে পারে এবং আপনার একটি public
রেফারেন্স এবং / অথবা গিটার থাকতে পারে।if
আপনার কোডে ও বনামের রাজ্যের পরিবর্তনের সংখ্যার উপর নির্ভর করে এটি এস বা এসের চেয়ে দ্রুত হতে পারে (টার্নআরউন্ডটি ৩-৪ সেকেন্ডের কাছাকাছি আশা করা যায় , তবে সর্বদা প্রথমে পরিমাপ করুন।switch()
if
if
std::function<>
ফাংশন পয়েন্টার উপর, আপনি পারে মধ্যে আপনার সমস্ত অবজেক্ট ডেটা পরিচালনা করতে পারবেন IBase
। এই বিন্দু থেকে, আপনার জন্য মান স্কিমেটিক্স থাকতে পারে IBase
(যেমন, std::vector<IBase>
কাজ করবে)। নোট করুন যে এটি আপনার সংকলক এবং এসটিএল কোডের উপর নির্ভর করে ধীর হতে পারে; std::function<>
ফাংশন পয়েন্টার বা এমনকি ভার্চুয়াল ফাংশনগুলির সাথে তুলনায় যখন বর্তমান বাস্তবায়নগুলি একটি ওভারহেড ঝোঁক দেয় (এটি ভবিষ্যতে পরিবর্তিত হতে পারে)।এখানে সংজ্ঞা দেওয়া হল abstract class
সি ++ স্ট্যান্ডার্ডের আছে
n4687
13.4.2
একটি বিমূর্ত শ্রেণি একটি শ্রেণি যা কেবলমাত্র অন্য কোনও শ্রেণির বেস শ্রেণি হিসাবে ব্যবহার করা যেতে পারে; বিমূর্ত শ্রেণীর কোনও বস্তু এটি থেকে উত্পন্ন ক্লাসের সাবোবজেক্টগুলি ছাড়া তৈরি করা যায় না। কোনও শ্রেণীর বিমূর্ত থাকে যদি এতে কমপক্ষে একটি খাঁটি ভার্চুয়াল ফাংশন থাকে।
class Shape
{
public:
// pure virtual function providing interface framework.
virtual int getArea() = 0;
void setWidth(int w)
{
width = w;
}
void setHeight(int h)
{
height = h;
}
protected:
int width;
int height;
};
class Rectangle: public Shape
{
public:
int getArea()
{
return (width * height);
}
};
class Triangle: public Shape
{
public:
int getArea()
{
return (width * height)/2;
}
};
int main(void)
{
Rectangle Rect;
Triangle Tri;
Rect.setWidth(5);
Rect.setHeight(7);
cout << "Rectangle area: " << Rect.getArea() << endl;
Tri.setWidth(5);
Tri.setHeight(7);
cout << "Triangle area: " << Tri.getArea() << endl;
return 0;
}
ফলাফল: আয়তক্ষেত্র অঞ্চল: 35 ত্রিভুজ অঞ্চল: 17
আমরা দেখেছি যে কীভাবে একটি বিমূর্ত শ্রেণি getArea () এবং অন্য দুটি শ্রেণীর ক্ষেত্রে একটি ইন্টারফেস সংজ্ঞায়িত করে একই ফাংশন বাস্তবায়িত করেছে তবে আকারের সাথে নির্দিষ্ট ক্ষেত্রটি গণনা করার জন্য বিভিন্ন অ্যালগরিদম সহ।