উত্সর্গীকৃত ক্লাস ফাংশন থেকে প্যারেন্ট ক্লাস ফাংশনটি কীভাবে কল করবেন?


602

আমি সি ++ ব্যবহার করে উদ্ভূত শ্রেণি থেকে পিতামাতার ফাংশনটিকে কীভাবে কল করব? উদাহরণস্বরূপ, আমার কাছে একটি ক্লাস বলা হয়েছে parent, এবং একটি ক্লাস রয়েছে childযা পিতামাতার কাছ থেকে নেওয়া। প্রতিটি ক্লাসের মধ্যে একটি printফাংশন থাকে। সন্তানের মুদ্রণ ফাংশনটির সংজ্ঞায় আমি পিতামাতার মুদ্রণ ফাংশনটিতে কল করতে চাই। আমি কীভাবে এটি করতে যাব?


উপরের সমস্ত সমাধান ধরে নিচ্ছে যে আপনার মুদ্রণ ফাংশনটি একটি স্থির পদ্ধতি। এই ঘটনা কি? পদ্ধতিটি যদি স্থির না হয় তবে উপরের সমাধানগুলি প্রাসঙ্গিক নয়।
হাফেজ

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

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


Antipattern যেখানে উদ্ভূত শ্রেণীর সবসময় প্রয়োজনীয় পিতা বা মাতা বর্গ ফাংশান কল হয় কল সুপার
রূফের

উত্তর:


774

আমি স্পষ্ট করে বলার ঝুঁকি নেব: আপনি ফাংশনটি কল করুন, যদি এটি বেস শ্রেণীর মধ্যে সংজ্ঞায়িত হয় তবে এটি স্বয়ংক্রিয়ভাবে উদ্ভূত শ্রেণিতে উপলব্ধ (যদি না হয় private)।

যদি উত্পন্ন শ্রেণিতে একই স্বাক্ষরের সাথে কোনও ফাংশন থাকে তবে আপনি বেস ক্লাসের নামটি দুটি কলোনের পরে যুক্ত করে এটি নিষ্ক্রিয় করতে পারেন base_class::foo(...)। আপনি জানানো হচ্ছে যে জাভা এবং C # মতো সি ++ নেই না "বেস শ্রেণী" (জন্য একটি শব্দ আছে superবা base) যেহেতু সি ++ সমর্থন একাধিক উত্তরাধিকার যা অস্পষ্টতা দেখা দিতে পারে।

class left {
public:
    void foo();
};

class right {
public:
    void foo();
};

class bottom : public left, public right {
public:
    void foo()
    {
        //base::foo();// ambiguous
        left::foo();
        right::foo();

        // and when foo() is not called for 'this':
        bottom b;
        b.left::foo();  // calls b.foo() from 'left'
        b.right::foo();  // call b.foo() from 'right'
    }
};

ঘটনাক্রমে, আপনি একই ক্লাস থেকে দুবার সরাসরি উপস্থাপন করতে পারবেন না কারণ অন্যটির উপর ভিত্তি করে কোনও বেস শ্রেণীর রেফারেন্স দেওয়ার উপায় নেই be

class bottom : public left, public left { // Illegal
};

30
কেন আপনি একই ক্লাস থেকে দু'বার উত্তরাধিকারী হতে চান?
পল ব্রিউকজেনস্কি

65
@ ব্লুজেম: ক্লাসিক ওওপিতে এটি কোনও তাত্পর্যপূর্ণ নয়, তবে জেনেরিক প্রোগ্রামিংয়ে template<class A, class B> class C: public A, public B {};আপনার কোডটি কীভাবে ব্যবহৃত হয় (যেটি এ এবং বি কে একই করে তোলে) তার উপর নির্ভর করে দুটি ধরণের একই হতে পারে, এটি দুটি বা তিনটি হতে পারে আপনি কী করেছিলেন সে সম্পর্কে সচেতন না এমন কারও কাছ থেকে বিমূর্ত স্তর স্তর।
এমিলিও গারাভাগলিয়া

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

4
আমি যখন সিপিপি ফাইলে এটি রাখার চেষ্টা করতাম তখন একটি সিডনোটে, আমাকে পাগল করে তোলে। আমার 'নেমস্পেস এসটিডি ব্যবহার' ছিল। 'বাম' name নামস্থানের কোথাও সংজ্ঞায়িত করা হয়েছে। উদাহরণটি সংকলন করবে না - আমাকে পাগল করে দিয়েছে :)। তারপরে আমি 'বাম' পরিবর্তন করে 'বামে' রেখেছি। উপায় দ্বারা দুর্দান্ত উদাহরণ।
মাথাই

72
@ মাথাই এবং এজন্য আপনার ব্যবহার করার কথা নয় using namespace std
জাব 21

193

অভিভাবক শ্রেণীর নাম দেওয়া হয়েছে Parentএবং শিশু শ্রেণীর নাম দেওয়া হয়েছে Child, আপনি এরকম কিছু করতে পারেন:

class Parent {
public:
    virtual void print(int x);
}

class Child : public Parent {
    void print(int x) override;
}

void Parent::print(int x) {
    // some default behavior
}

void Child::print(int x) {
    // use Parent's print method; implicitly passes 'this' to Parent::print
    Parent::print(x);
}

নোট করুন Parentএটি শ্রেণীর আসল নাম এবং কোনও কীওয়ার্ড নয়।


অবশ্যই, এই শুধুমাত্র যদি বেস কল অন্যান্য যুক্তিবিজ্ঞান সঙ্গে interspersed করা হয়েছে, অন্যথায় ফাংশন অগ্রাহ্য করে কোনো লাভ হতে চাই উপযোগী হতে হবে, তাই হয়তো এটা একটু এর খুব টু-পয়েন্ট;)
underscore_d

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

@ আইহানেই আকর্ষণীয় মনে হচ্ছে তবে দুঃখিত, আমি এখনও এটি আঁকড়ে ধরছি না। foo()এখানে কি অনুরূপ print()বা পৃথক ফাংশন? এবং আপনি কি privateবেস থেকে উত্তরাধিকারসূত্রে প্রাপ্ত বিবরণগুলি গোপন করার জন্য উত্তরাধিকার ব্যবহার করে এবং আপনি যে publicজিনিসগুলি প্রকাশ করতে চান তার জন্য ছায়া ফাংশন সরবরাহ করে বোঝাতে চান?
আন্ডারস্কোর_

@underscore_d হ্যাঁ, foo()অনুরূপ ছিল print()print()এই প্রসঙ্গে এটি আরও অর্থবোধ করবে বলে আমি মনে করি ব্যবহারে ফিরে যেতে দিন । ধরা যাক যে কেউ একটি শ্রেণি তৈরি করেছে যা একটি নির্দিষ্ট ডেটাটাইপের উপর কিছু সেট পরিচালনা করে, কিছু অ্যাক্সেসরকে প্রকাশ করে, এবং তার একটি print(obj&)পদ্ধতি ছিল । আমার একটি নতুন ক্লাস দরকার যা কাজ করে array-of-objতবে অন্য সব কিছু একই। প্রচুর নকল কোডে রচনা ফলাফল। উত্তরাধিকার হ্রাস করা যায়, print(array-of-obj&) লুপ print(obj&)print(obj&)
কলিংয়ে

@ আসর_সো_আর এই ধারণাটি নিয়ে ভবিষ্যদ্বাণী করা হয় যে আমি মূল অভিভাবক শ্রেণির সাধারণ অংশগুলি বের করতে পারি না বা এটি করা অবিশ্বাস্যভাবে ব্যয়বহুল। ব্যক্তিগত উত্তরাধিকার কাজ করতে পারে, তবে তারপরে আপনি যে সর্বজনীন প্রবেশাধিকারীর উপর নির্ভর করেছিলেন তা হারাবেন - এবং এর জন্য কোডটির নকল করা দরকার।
iheanyi

32

যদি আপনার বেস ক্লাস বলা হয় Baseএবং আপনার ফাংশনটি বলা হয় FooBar()আপনি সরাসরি এটি ব্যবহার করে কল করতে পারেনBase::FooBar()

void Base::FooBar()
{
   printf("in Base\n");
}

void ChildOfBase::FooBar()
{
  Base::FooBar();
}

28

এমএসভিসিতে একটি মাইক্রোসফ্টের নির্দিষ্ট কীওয়ার্ড রয়েছে: __সুপার


এমএসডিএন: আপনাকে সুস্পষ্টভাবে বলতে দেয় যে আপনি যে ক্রিয়াকে ওভাররাইড করছেন তার জন্য আপনি একটি বেস-ক্লাস বাস্তবায়ন কল করছেন।

// deriv_super.cpp
// compile with: /c
struct B1 {
   void mf(int) {}
};

struct B2 {
   void mf(short) {}

   void mf(char) {}
};

struct D : B1, B2 {
   void mf(short) {
      __super::mf(1);   // Calls B1::mf(int)
      __super::mf('s');   // Calls B2::mf(char)
   }
};


5
হ্যাঁ, আমি typdefপিতামাতার মতো কিছু পছন্দ করি super
থমাস এডিং

26
আমি এর ব্যবহারকে ন্যায়সঙ্গত করার চেষ্টা করব না __super; বিকল্প পরামর্শ হিসাবে আমি এখানে এটি উল্লেখ করেছি। বিকাশকারীদের তাদের সংকলকটি জানতে হবে এবং এর দক্ষতার পক্ষে ভাল ধারণা করা উচিত।
আন্দ্রে

13
আমি বরং কাউকে এটি ব্যবহার থেকে নিরুৎসাহিত করব, কারণ এটি কোডের বহনযোগ্যতার মারাত্মকভাবে বাধা দেয়।
এরবুর্থ

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

7
"বিকাশকারীদের তাদের সংকলকটি জানতে হবে" এই যুক্তিটি এবং মানসম্মত বৈশিষ্ট্যগুলি অন্তর্ভুক্তি নয়, যা আই 6 এর দিকে পরিচালিত করেছে ...
e2-e4

5

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

#include<iostream>
using namespace std;

class Parent
{
  protected:
    virtual void fun(int i)
    {
      cout<<"Parent::fun functionality write here"<<endl;
    }
    void fun1(int i)
    {
      cout<<"Parent::fun1 functionality write here"<<endl;
    }
    void fun2()
    {

      cout<<"Parent::fun3 functionality write here"<<endl;
    }

};

class Child:public Parent
{
  public:
    virtual void fun(int i)
    {
      cout<<"Child::fun partial functionality write here"<<endl;
      Parent::fun(++i);
      Parent::fun2();
    }
    void fun1(int i)
    {
      cout<<"Child::fun1 partial functionality write here"<<endl;
      Parent::fun1(++i);
    }

};
int main()
{
   Child d1;
   d1.fun(1);
   d1.fun1(2);
   return 0;
}

আউটপুট:

$ g++ base_function_call_from_derived.cpp
$ ./a.out 
Child::fun partial functionality write here
Parent::fun functionality write here
Parent::fun3 functionality write here
Child::fun1 partial functionality write here
Parent::fun1 functionality write here

1
কিছু উদাহরণ আনার জন্য আপনাকে ধন্যবাদ virtual!
এম.আইওয়ান

5

প্যারেন্ট স্কোপ রেজুলেশন অপারেটরের সাথে প্যারেন্ট পদ্ধতিতে কল করুন।

মূল :: পদ্ধতি ()

class Primate {
public:
    void whatAmI(){
        cout << "I am of Primate order";
    }
};

class Human : public Primate{
public:
    void whatAmI(){
        cout << "I am of Human species";
    }
    void whatIsMyOrder(){
        Primate::whatAmI(); // <-- SCOPE RESOLUTION OPERATOR
    }
};

-15
struct a{
 int x;

 struct son{
  a* _parent;
  void test(){
   _parent->x=1; //success
  }
 }_son;

 }_a;

int main(){
 _a._son._parent=&_a;
 _a._son.test();
}

রেফারেন্স উদাহরণ।


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

3
এই উত্তরটি নেস্টেড ক্লাস সম্পর্কে যখন প্রশ্নটি উদ্ভূত শ্রেণি সম্পর্কে ছিল (যদিও 'পিতামাতা' এবং 'শিশু' শব্দটি কিছুটা মিসলাইডিং) এবং তাই প্রশ্নের কোনও উত্তর দেয় না।
জোহানেস ম্যাটোকিক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.