ভার্চুয়াল / খাঁটি ভার্চুয়াল ব্যাখ্যা করা হয়েছে


346

কোনও ফাংশনটি ভার্চুয়াল হিসাবে সংজ্ঞায়িত করা এবং খাঁটি ভার্চুয়াল হিসাবে একই হলে এর অর্থ কী?

উত্তর:


339

থেকে উইকিপিডিয়ার ভার্চুয়াল ফাংশন ...

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

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

এটি অ-ভার্চুয়াল ফাংশনগুলির বিপরীতে, যা এখনও একটি উদ্ভূত শ্রেণিতে ওভাররাইড করা যেতে পারে, তবে "নতুন" সংস্করণটি কেবল উত্পন্ন শ্রেণীর দ্বারা এবং নীচে ব্যবহার করা হবে, তবে বেস শ্রেণীর কার্যকারিতাটি একেবারেই বদলাবে না।

যেহেতু ..

একটি খাঁটি ভার্চুয়াল ফাংশন বা খাঁটি ভার্চুয়াল পদ্ধতি হ'ল একটি ভার্চুয়াল ফাংশন যা ডেরিভড ক্লাসটি বিমূর্ত না হলে কোনও উদ্ভূত শ্রেণীর দ্বারা প্রয়োগ করা প্রয়োজন।

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

ভার্চুয়াল বেস ক্লাসের কার্যকারিতা ওভাররাইড করার একটি উপায় সরবরাহ করে এবং খাঁটি-ভার্চুয়াল এর প্রয়োজন হয়।


10
সুতরাং ... খাঁটি ভার্চুয়াল কিওয়ার্ড, বা ব্যবহৃত একটি শব্দ?
জাস্টিন 15

197
ভার্চুয়াল শূন্য ফাংশন () = 0; খাঁটি ভার্চুয়াল is "= 0" নির্দেশ করে শুদ্ধি।
Goz

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

14
আমি বিশ্বাস করি স্ট্রোস্ট্রুপ বলেছিলেন যে তিনি একটি pureকীওয়ার্ড যুক্ত করতে চেয়েছিলেন তবে বেল ল্যাবগুলি সি ++ এর একটি বড় রিলিজ করতে চলেছে, এবং তার ব্যবস্থাপক সেই দেরি পর্যায়ে এটি অনুমতি দেবে না। কীওয়ার্ড যুক্ত করা বড় বিষয়।
কোয়ার্ক

14
এটি একটি ভাল উত্তর নয়। যে কোনও পদ্ধতি কেবল ভার্চুয়াল নয়, ওভাররাইড করা যেতে পারে। আরও তথ্যের জন্য আমার উত্তর দেখুন।
আসিক

212

আমি এখানে উইকিপিডিয়ায় ভার্চুয়াল সম্পর্কিত সংজ্ঞা সম্পর্কে মন্তব্য করতে চাই several [এই উত্তরটি লেখার সময়,] উইকিপিডিয়া একটি ভার্চুয়াল পদ্ধতিটিকে এমন একটি সংজ্ঞায়িত করেছিল যা সাবক্লাসে ওভাররাইড করা যায়। [ভাগ্যক্রমে, উইকিপিডিয়াটি তখন থেকেই সম্পাদনা করা হয়েছে, এবং এটি এখন এটি সঠিকভাবে ব্যাখ্যা করে]] এটি ভুল: কোনও পদ্ধতি, কেবল ভার্চুয়াল নয়, সাবক্লাসে ওভাররাইড করা যেতে পারে। ভার্চুয়াল যা করে তা হ'ল আপনাকে বহুমুখিতা দেওয়া, অর্থাৎ রান-টাইমে কোনও পদ্ধতির সর্বাধিক উদ্ভূত ওভাররাইডে নির্বাচন করার ক্ষমতা

নিম্নলিখিত কোড বিবেচনা করুন:

#include <iostream>
using namespace std;

class Base {
public:
    void NonVirtual() {
        cout << "Base NonVirtual called.\n";
    }
    virtual void Virtual() {
        cout << "Base Virtual called.\n";
    }
};
class Derived : public Base {
public:
    void NonVirtual() {
        cout << "Derived NonVirtual called.\n";
    }
    void Virtual() {
        cout << "Derived Virtual called.\n";
    }
};

int main() {
    Base* bBase = new Base();
    Base* bDerived = new Derived();

    bBase->NonVirtual();
    bBase->Virtual();
    bDerived->NonVirtual();
    bDerived->Virtual();
}

এই প্রোগ্রামের আউটপুট কি?

Base NonVirtual called.
Base Virtual called.
Base NonVirtual called.
Derived Virtual called.

প্রাপ্ত ব্যাসের প্রতিটি পদ্ধতি ওভাররাইড করে: কেবল ভার্চুয়ালটিই নয়, অ-ভার্চুয়ালও।

আমরা দেখতে পাই যে যখন আপনার কাছে বেস-পয়েন্টার-থেকে-ডেরিভড (বিডেরাইভড) থাকে তখন নন-ভার্চুয়ালকে কল করে বেস ক্লাস বাস্তবায়ন। এটি সংকলন-সময় সমাধান করা হয়েছে: সংকলকটি দেখেছে যে বিডেরাইভড একটি বেস *, নন ভার্চুয়াল ভার্চুয়াল নয়, সুতরাং এটি ক্লাস বেসের উপর রেজোলিউশন করে।

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

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


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

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

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

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

3
Derived*পয়েন্ট হোম চালানোর জন্য একই ফাংশন কলগুলির সাথে একটি যুক্ত করা সহায়ক হতে পারে । অন্যথায় দুর্দান্ত উত্তর
জেফ জোনস

114

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

class Animal
{
  public:
    virtual int GetNumberOfLegs() = 0;
};

class Duck : public Animal
{
  public:
     int GetNumberOfLegs() { return 2; }
};

class Horse : public Animal
{
  public:
     int GetNumberOfLegs() { return 4; }
};

void SomeFunction(Animal * pAnimal)
{
  cout << pAnimal->GetNumberOfLegs();
}

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

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

আমরা যদি এটি করি:

Duck d;
SomeFunction(&d);

এটি '2' আউটপুট চাই। আমরা যদি এটি করি:

Horse h;
SomeFunction(&h);

এটি '4' আউটপুট চাই। আমরা এটি করতে পারি না:

Animal a;
SomeFunction(&a);

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

খাঁটি ভার্চুয়াল ফাংশনগুলি বেশিরভাগ সংজ্ঞায়িত করতে ব্যবহৃত হয়:

ক) বিমূর্ত ক্লাস

এগুলি বেস ক্লাস যেখানে আপনাকে সেগুলি থেকে উদ্ভূত করতে হবে এবং তারপরে খাঁটি ভার্চুয়াল ফাংশন প্রয়োগ করতে হবে।

খ) ইন্টারফেস

এইগুলি 'খালি' শ্রেণি যেখানে সমস্ত ফাংশনগুলি খাঁটি ভার্চুয়াল এবং তাই আপনাকে সমস্ত ক্রিয়াকলাপ উদ্ঘাটন করতে হবে এবং তারপরে প্রয়োগ করতে হবে।


আপনার উদাহরণে, আপনি # 4 করতে পারবেন না কারণ আপনি খাঁটি ভার্চুয়াল পদ্ধতির কোনও বাস্তবায়ন সরবরাহ করেন নি। এটি কঠোরভাবে নয় কারণ পদ্ধতিটি খাঁটি ভার্চুয়াল।
ইহিয়ানী

@ iheanyi আপনি বেস ক্লাসে খাঁটি ভার্চুয়াল পদ্ধতিতে প্রয়োগকরণ সরবরাহ করতে পারবেন না। অতএব কেস # 4 এখনও ত্রুটি।
প্রসাদ

32

একটি সি ++ শ্রেণিতে ভার্চুয়াল হ'ল মূলশব্দ যা এটি নির্ধারণ করে যে একটি পদ্ধতি একটি সাবক্লাসকে ওভাররাইড করা যায় (অর্থাত্ প্রয়োগ করা হয়)। উদাহরণ স্বরূপ:

class Shape 
{
  public:
    Shape();
    virtual ~Shape();

    std::string getName() // not overridable
    {
      return m_name;
    }

    void setName( const std::string& name ) // not overridable
    {
      m_name = name;
    }

  protected:
    virtual void initShape() // overridable
    {
      setName("Generic Shape");
    }

  private:
    std::string m_name;
};

এক্ষেত্রে একটি সাবক্লাস কিছু বিশেষ কাজ করার জন্য ইনশাফ ফাংশনটিকে ওভাররাইড করতে পারে:

class Square : public Shape
{
  public: 
    Square();
    virtual ~Square();

  protected:
    virtual void initShape() // override the Shape::initShape function
    {
      setName("Square");
    }
}

শব্দটি বিশুদ্ধ ভার্চুয়াল ভার্চুয়াল ফাংশন একটি উপশ্রেণী দ্বারা বাস্তবায়িত করা প্রয়োজন এবং বেস বর্গ দ্বারা বাস্তবায়িত হয়নি যে বোঝায়। আপনি ভার্চুয়াল কীওয়ার্ড ব্যবহার করে এবং পদ্ধতি ঘোষণার শেষে একটি = 0 যুক্ত করে কোনও পদ্ধতিকে খাঁটি ভার্চুয়াল হিসাবে মনোনীত করেন ।

সুতরাং, আপনি যদি শেপ :: ইনিশপকে খাঁটি ভার্চুয়াল তৈরি করতে চান তবে আপনি নিম্নলিখিতটি করবেন:

class Shape 
{
 ...
    virtual void initShape() = 0; // pure virtual method
 ... 
};

আপনার ক্লাসে একটি খাঁটি ভার্চুয়াল পদ্ধতি যুক্ত করে আপনি ক্লাসটিকে একটি বিমূর্ত বেস বর্গ তৈরি করেন যা বাস্তবায়ন থেকে ইন্টারফেসকে পৃথক করার পক্ষে খুব কার্যকর।


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

2
এবং "getName ফাংশনটি একটি সাবক্লাস দ্বারা প্রয়োগ করা যায় না" বেশ সঠিক নয়। সাবক্লাসগুলি পদ্ধতিটি কার্যকর করতে পারে (ডাব্লু / একই বা ভিন্ন স্বাক্ষর) তবে সেই বাস্তবায়ন পদ্ধতিটিকে ওভাররাইড করবে না। আপনি সার্কেলটিকে একটি সাবক্লাস হিসাবে বাস্তবায়ন করতে এবং "std :: স্ট্রিং সার্কেল :: getName ()" প্রয়োগ করতে পারেন - তারপরে আপনি কোনও বৃত্ত উদাহরণের জন্য কোনও পদ্ধতিতে কল করতে পারেন। তবে যদি শেপ পয়েন্টার বা রেফারেন্সের মাধ্যমে ব্যবহার করা হয় তবে সংকলকটি শেপকে ফোন করবে: getName ()।
এনভিআরএম

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

@ নিকহাদদাদ ওল্ড থ্রেড, কিন্তু আপনি কেন নিজের ভেরিয়েবলটিকে ডেকে আশ্চর্য করছেন m_name। কী m_মানে?
Tqn

1
@ টিকিএন ধরে নিখাদদাদ সম্মেলনগুলি অনুসরণ করেছে, এম_নেম একটি নামকরণ কনভেনশন যা সাধারণত হাঙ্গেরিয়ান স্বরলিপি নামে পরিচিত। মি একটি কাঠামো / শ্রেণির সদস্য, পূর্ণসংখ্যার নির্দেশ করে।
কেটকম্প

16

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

আউট যে বিশুদ্ধ-ভার্চুয়াল পদ্ধতি @quark পয়েন্ট পারেন একটি বাস্তবায়ন আছে, কিন্তু যেমন বিশুদ্ধ-ভার্চুয়াল পদ্ধতি ওভাররাইড করা যেতে হবে, ডিফল্ট বাস্তবায়ন সরাসরি বলা যায় না। এখানে একটি ডিফল্ট সহ খাঁটি-ভার্চুয়াল পদ্ধতির উদাহরণ রয়েছে:

#include <cstdio>

class A {
public:
    virtual void Hello() = 0;
};

void A::Hello() {
    printf("A::Hello\n");
}

class B : public A {
public:
    void Hello() {
        printf("B::Hello\n");
        A::Hello();
    }
};

int main() {
    /* Prints:
           B::Hello
           A::Hello
    */
    B b;
    b.Hello();
    return 0;
}

মন্তব্য অনুসারে, সংকলন ব্যর্থ হবে কি না তা সংকলক-নির্দিষ্ট। কমপক্ষে জিসিসিতে ৪.৩.৩, এটি সংকলন করবে না:

class A {
public:
    virtual void Hello() = 0;
};

int main()
{
    A a;
    return 0;
}

আউটপুট:

$ g++ -c virt.cpp 
virt.cpp: In function int main()’:
virt.cpp:8: error: cannot declare variable a to be of abstract type A
virt.cpp:1: note:   because the following virtual functions are pure within A’:
virt.cpp:3: note:   virtual void A::Hello()

আপনি অবশ্যই শ্রেণীর কোনও উদাহরণ ইনস্ট্যান্ট করতে চাইলে এটি অবশ্যই ওভাররাইড করা উচিত। আপনি যদি কোনও দৃষ্টান্ত তৈরি না করেন তবে কোডটি ঠিক ঠিক সংকলন করবে।
গ্লেন

1
সংকলন ব্যর্থ হবে না। যদি কোনও (খাঁটি) ভার্চুয়াল পদ্ধতির বাস্তবায়ন না হয় তবে সেই শ্রেণি / অবজেক্টটি ইনস্ট্যান্ট করা যাবে না cannot এটি লিঙ্ক নাও পারে তবে এটি সংকলন করবে।
টিম

@ গ্লেন, @ টিটিম: কোন সংকলনে? আমি যখন একটি প্রোগ্রাম সংকলন করার চেষ্টা করি যা একটি বিমূর্ত শ্রেণি তৈরি করে, এটি সংকলন করে না।
জন মিলিকিন

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

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

9

ভার্চুয়াল কীওয়ার্ডটি কীভাবে কাজ করে?

ধরে নিন যে ম্যান একটি বেস ক্লাস, ভারতীয় থেকে উদ্ভূত মানুষ।

Class Man
{
 public: 
   virtual void do_work()
   {}
}

Class Indian : public Man
{
 public: 
   void do_work()
   {}
}

ডু-ওয়ার্ক () কে ভার্চুয়াল হিসাবে ঘোষণার অর্থ হ'ল: যা করতে ডু-ওয়ার্ক () কল করা কেবল রান-টাইমে নির্ধারিত হবে।

ধরুন আমি করি,

Man *man;
man = new Indian();
man->do_work(); // Indian's do work is only called.

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

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

সেখানে আরও একটি বিভ্রান্তিমূলক মন্তব্য বলে মনে হচ্ছে যা বলছে,

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

এটা ভুল! খাঁটি ভার্চুয়াল ফাংশনগুলিরও একটি শরীর থাকতে পারে এবং প্রয়োগ করা যেতে পারে! সত্যটি একটি বিমূর্ত শ্রেণীর 'খাঁটি ভার্চুয়াল ফাংশনটিকে স্ট্যাটিকালি বলা যেতে পারে! দুটি খুব ভাল লেখক হলেন বজ্জন স্ট্রস্ট্রপ এবং স্টান লিপম্যান .... কারণ তারা ভাষাটি লিখেছিলেন।


2
দুর্ভাগ্যক্রমে একবার উত্তর উত্তোলন শুরু হলে, সমস্ত অন্যান্য উপেক্ষা করা হবে। এমনকি তারা আরও ভাল হতে পারে।
এলটি ওয়ার্ফ

3

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

খাঁটি ভার্চুয়াল ফাংশনটি হ'ল বেস ক্লাসের সাথে কোনও সংজ্ঞা নেই। বেস শ্রেণিতে এর কোন প্রয়োগ নেই। যে কোনও উদ্ভূত শ্রেণীর অবশ্যই এই ক্রিয়াকে ওভাররাইড করতে হবে।


2

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

অবজেক্ট ওরিয়েন্টেড প্রোগ্রামিংয়ের জন্য তিনটি মৌলিক ধারণা প্রয়োজন: এনক্যাপসুলেশন, উত্তরাধিকার এবং গতিশীল পদ্ধতির বাইন্ডিং।

এনক্যাপসুলেশন কোনও বিমূর্ততার বাস্তবায়ন বিবরণকে একটি সাধারণ ইন্টারফেসের আড়ালে লুকিয়ে রাখতে দেয়।

উত্তরাধিকার হ'ল নতুন বিমূর্তিটি কিছু বিদ্যমান বিমূর্তির সম্প্রসারণ বা পরিমার্জন হিসাবে সংজ্ঞায়িত করার অনুমতি দেয়, এর কিছু বা সমস্ত বৈশিষ্ট্য স্বয়ংক্রিয়ভাবে প্রাপ্ত হয়।

গতিশীল পদ্ধতির বাইন্ডিং পুরানো বিমূর্ততা প্রত্যাশা করে এমন প্রসঙ্গে ব্যবহৃত হলেও এমনকি নতুন বিমূর্তিটিকে তার নতুন আচরণ প্রদর্শন করতে দেয়।


1

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

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

ভার্চুয়াল ডিফল্ট জাভা আচরণের সাথে মিলে যায়, যখন উত্পন্ন শ্রেণিটি বেস শ্রেণীর কোনও পদ্ধতিকে ওভাররাইড করে।

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


0

খাঁটি ভার্চুয়াল ফাংশন

এই কোড চেষ্টা করুন

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()=0;

};

class anotherClass:aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"hellow World";
    }

};
int main()
{
    //aClassWithPureVirtualFunction virtualObject;
    /*
     This not possible to create object of a class that contain pure virtual function
    */
    anotherClass object;
    object.sayHellow();
}

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

ভার্চুয়াল ফাংশন

অন্য কোড চেষ্টা করুন

#include <iostream>
using namespace std;
class aClassWithPureVirtualFunction
{

public:

    virtual void sayHellow()
    {
        cout<<"from base\n";
    }

};

class anotherClass:public aClassWithPureVirtualFunction
{

public:

    void sayHellow()
    {

        cout<<"from derived \n";
    }

};
int main()
{
    aClassWithPureVirtualFunction *baseObject=new aClassWithPureVirtualFunction;
    baseObject->sayHellow();///call base one

    baseObject=new anotherClass;
    baseObject->sayHellow();////call the derived one!

}

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


হাহা, এখানে কী ভুল তা বুঝতে আমাকে 30 সেকেন্ড সময় লেগেছে ... হ্যালো ডাব্লু :)
হ্যান্স

0

"ভার্চুয়াল ফাংশন বা ভার্চুয়াল পদ্ধতি হ'ল একটি ফাংশন বা পদ্ধতি যা এর আচরণ একই স্বাক্ষর সহ একটি ফাংশন দ্বারা উত্তরাধিকার সূত্রে শ্রেণীর মধ্যে ওভাররাইড করা যেতে পারে" - উইকিপিডিয়া

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

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


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

  • ভার্চুয়াল ফাংশনগুলি সাধারণ শ্রেণিতে ঘোষিত এবং সংজ্ঞায়িত হয়।

  • খাঁটি ভার্চুয়াল ফাংশনটি অবশ্যই "= 0" দিয়ে শেষ হতে হবে এবং এটি কেবল বিমূর্ত শ্রেণিতে ঘোষণা করা যেতে পারে।

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


@ শেশেডস হিসাবে একই নোট: প্রকৃতপক্ষে খাঁটি ভার্চুয়াল ফাংশনটির এর সংজ্ঞা থাকতে পারে ...
জারেক সি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.