শ্রেণি ডেটা সদস্যের নির্দেশক ":: *"


242

আমি এই অদ্ভুত কোড স্নিপেট জুড়ে এসেছি যা সূক্ষ্ম সংকলন করে:

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;
    return 0;
}

সি ++ এর কেন এই শ্রেণীর কোনও অ স্থিতিশীল ডেটা সদস্যের কাছে এই পয়েন্টার রয়েছে? রিয়েল কোডে এই অদ্ভুত পয়েন্টারটির ব্যবহার কী ?


এখানে আমি কোথায় তা খুঁজে পেলে আমিও বিভ্রান্ত হয় ... কিন্তু এখন জ্ঞান করে তোলে: stackoverflow.com/a/982941/211160
HostileFork বলেছেন Dont ট্রাস্ট দঃপূঃ

উত্তর:


189

এটি একটি "সদস্যের পয়েন্টার" - নিম্নলিখিত কোডটি এর ব্যবহারের চিত্রিত করে:

#include <iostream>
using namespace std;

class Car
{
    public:
    int speed;
};

int main()
{
    int Car::*pSpeed = &Car::speed;

    Car c1;
    c1.speed = 1;       // direct access
    cout << "speed is " << c1.speed << endl;
    c1.*pSpeed = 2;     // access via pointer to member
    cout << "speed is " << c1.speed << endl;
    return 0;
}

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

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

void Apply( SomeClass * c, void (SomeClass::*func)() ) {
    // do hefty pre-call processing
    (c->*func)();  // call user specified function
    // do hefty post-call processing
}

চারপাশে প্রথম বন্ধনী c->*funcপ্রয়োজনীয় কারণ ->*অপারেটরের ফাংশন কল অপারেটরের চেয়ে কম অগ্রাধিকার রয়েছে।


3
আপনি কোথায় এমন কার্যকর পরিস্থিতিগুলির উদাহরণ দেখাতে পারেন? ধন্যবাদ।
আশ্বিন নানজাপ্পা

আমার কাছে অন্য এসও উত্তরের একটি বৈশিষ্ট্য শ্রেণিতে পয়েন্টার-টু-সদস্য ব্যবহারের উদাহরণ রয়েছে ।
মাইক ডিসিমোন

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


3
আমি সম্প্রতি সিরিয়ালাইজেশন কাঠামোর ডেটা সদস্যদের পয়েন্টার ব্যবহার করেছি। স্ট্যাটিক মার্শালার অবজেক্টটি সিরিয়ালাইজেবল ডেটা সদস্যগুলিতে পয়েন্টারযুক্ত মোড়কের তালিকার সাথে সূচনা করা হয়েছিল। এই কোডের একটি প্রাথমিক প্রোটোটাইপ।
আলেক্সি বিরিউকভভ

79

এটি আমি সবচেয়ে সহজ উদাহরণ যা এই বৈশিষ্ট্যটি প্রাসঙ্গিক যেখানে বিরল ক্ষেত্রে তা বোঝায়:

#include <iostream>

class bowl {
public:
    int apples;
    int oranges;
};

int count_fruit(bowl * begin, bowl * end, int bowl::*fruit)
{
    int count = 0;
    for (bowl * iterator = begin; iterator != end; ++ iterator)
        count += iterator->*fruit;
    return count;
}

int main()
{
    bowl bowls[2] = {
        { 1, 2 },
        { 3, 5 }
    };
    std::cout << "I have " << count_fruit(bowls, bowls + 2, & bowl::apples) << " apples\n";
    std::cout << "I have " << count_fruit(bowls, bowls + 2, & bowl::oranges) << " oranges\n";
    return 0;
}

এখানে লক্ষ্য করার বিষয়টি হল পয়েন্টারটি গণনা_ফলে পাস হয়েছে। এটি আপনাকে পৃথক গণনা_ অ্যাপলস এবং কাউন্ট_অরেঞ্জ ফাংশন লিখতে বাঁচায়।


3
এটা হতে না করা উচিত &bowls.applesএবং &bowls.oranges? &bowl::applesএবং &bowl::orangesকোন কিছুর প্রতি নির্দেশ দেয় না।
ড্যান নিসেনবাউম

19
&bowl::applesএবং &bowl::orangesকোনও বস্তুর সদস্যদের দিকে ইঙ্গিত করবেন না ; তারা একটি শ্রেণীর সদস্যদের দিকে ইঙ্গিত করে । কোনও কিছুর দিকে ইঙ্গিত করার আগে তাদেরকে একটি আসল বস্তুর সাথে পয়েন্টারের সাথে একত্রিত করা দরকার। ->*অপারেটরের সাথে এই সংমিশ্রণটি অর্জন করা হয় ।
জন ম্যাকফার্লেন

58

আর একটি অ্যাপ্লিকেশন হস্তক্ষেপমূলক তালিকা। উপাদানটির ধরণ তালিকাটিকে তার পরবর্তী / পূর্ববর্তী পয়েন্টারগুলি কী তা বলতে পারে। সুতরাং তালিকাটি হার্ড-কোডেড নাম ব্যবহার করে না তবে এখনও বিদ্যমান পয়েন্টারগুলি ব্যবহার করতে পারে:

// say this is some existing structure. And we want to use
// a list. We can tell it that the next pointer
// is apple::next.
struct apple {
    int data;
    apple * next;
};

// simple example of a minimal intrusive list. Could specify the
// member pointer as template argument too, if we wanted:
// template<typename E, E *E::*next_ptr>
template<typename E>
struct List {
    List(E *E::*next_ptr):head(0), next_ptr(next_ptr) { }

    void add(E &e) {
        // access its next pointer by the member pointer
        e.*next_ptr = head;
        head = &e;
    }

    E * head;
    E *E::*next_ptr;
};

int main() {
    List<apple> lst(&apple::next);

    apple a;
    lst.add(a);
}

যদি এটি সত্যিই একটি লিঙ্কযুক্ত তালিকাগুলি থাকে তবে আপনি কি এর মতো কিছু চান না: অকার্যকর অ্যাড (ই * ই) {ই -> * Next_ptr = মাথা; মাথা = ই; } ??
eeeeaaii

4
@ আমি আপনাকে রেফারেন্সের পরামিতিগুলি পড়ার জন্য পরামর্শ দিচ্ছি। আমি যা করেছি তা মূলত আপনি যা করেছেন তার সমতুল্য।
জোহানেস স্কাউব -

আপনার কোড উদাহরণের জন্য +1, তবে আমি পয়েন্টার-টু-মেম্বার ব্যবহারের জন্য কোনও প্রয়োজনীয়তা দেখিনি, অন্য কোনও উদাহরণ?
অ্যালকোট

3
@Alcott: আপনি এটি অন্যান্য আবেদন করতে পারেন কাঠামো যেখানে পরবর্তী পয়েন্টার নামে নয় লিঙ্ক-তালিকা থাকা একই next
অিক্টোফায়

41

সিগন্যাল প্রসেসিং / নিয়ন্ত্রণ সিস্টেমগুলি থেকে আমি এখনই কাজ করছি এমন একটি বাস্তব-বিশ্বের উদাহরণ:

মনে করুন আপনার কাছে এমন কিছু কাঠামো রয়েছে যা আপনি যে ডেটা সংগ্রহ করছেন তা উপস্থাপন করে:

struct Sample {
    time_t time;
    double value1;
    double value2;
    double value3;
};

এখন ধরুন যে আপনি সেগুলি ভেক্টর হিসাবে স্টাফ করুন:

std::vector<Sample> samples;
... fill the vector ...

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

double Mean(std::vector<Sample>::const_iterator begin, 
    std::vector<Sample>::const_iterator end,
    double Sample::* var)
{
    float mean = 0;
    int samples = 0;
    for(; begin != end; begin++) {
        const Sample& s = *begin;
        mean += s.*var;
        samples++;
    }
    mean /= samples;
    return mean;
}

...
double mean = Mean(samples.begin(), samples.end(), &Sample::value2);

দ্রষ্টব্য আরও সংক্ষিপ্ত টেম্পলেট-ফাংশন পদ্ধতির জন্য 2016/08/05 সম্পাদিত Note

এবং অবশ্যই, আপনি যেকোন ফরোয়ার্ড-ইটারেটর এবং যে কোনও মান ধরণের যা নিজের সাথে সংযোজন এবং আকার_টি দ্বারা বিভাগকে সমর্থন করে তার কোনও গড় গণনা করতে এটি টেমপ্লেট করতে পারেন:

template<typename Titer, typename S>
S mean(Titer begin, const Titer& end, S std::iterator_traits<Titer>::value_type::* var) {
    using T = typename std::iterator_traits<Titer>::value_type;
    S sum = 0;
    size_t samples = 0;
    for( ; begin != end ; ++begin ) {
        const T& s = *begin;
        sum += s.*var;
        samples++;
    }
    return sum / samples;
}

struct Sample {
    double x;
}

std::vector<Sample> samples { {1.0}, {2.0}, {3.0} };
double m = mean(samples.begin(), samples.end(), &Sample::x);

সম্পাদনা - উপরের কোডটিতে পারফরম্যান্সের প্রভাব রয়েছে

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

এই কোডটির কার্যকারিতা বিবেচনা করুন:

struct Sample {
  float w, x, y, z;
};

std::vector<Sample> series = ...;

float sum = 0;
int samples = 0;
for(auto it = series.begin(); it != series.end(); it++) {
  sum += *it.x;
  samples++;
}
float mean = sum / samples;

অনেক স্থাপত্যে, এর একটি উদাহরণ Sample ক্যাশে লাইন পূরণ করবে। লুপের প্রতিটি পুনরাবৃত্তির উপর, একটি নমুনা স্মৃতি থেকে ক্যাশে টানা হবে। ক্যাশে লাইন থেকে 4 বাইট ব্যবহার করা হবে এবং বাকীটি ফেলে দেওয়া হবে এবং পরবর্তী পুনরাবৃত্তির ফলস্বরূপ অন্য ক্যাশে মিস, মেমরি অ্যাক্সেস এবং এর ফলে দেখা যাবে।

এটি করা আরও ভাল:

struct Samples {
  std::vector<float> w, x, y, z;
};

Samples series = ...;

float sum = 0;
float samples = 0;
for(auto it = series.x.begin(); it != series.x.end(); it++) {
  sum += *it;
  samples++;
}
float mean = sum / samples;

এখন যখন প্রথম এক্স মানটি মেমরি থেকে লোড করা হয়, পরবর্তী তিনটিও ক্যাশে লোড করা হবে (উপযুক্ত প্রান্তিককরণটি মনে করুন), পরবর্তী তিনটি পুনরাবৃত্তির জন্য আপনার কোনও মান বোঝানো হবে না।

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

ওয়াইএমএমভি - আপনার অ্যালগোরিদম অনুসারে আপনার ডেটা স্ট্রাকচার ডিজাইন করুন।


এটি দুর্দান্ত। আমি খুব অনুরূপ কিছু বাস্তবায়ন করতে চলেছি, এবং এখন আমার অদ্ভুত বাক্য গঠন বের করতে হবে না! ধন্যবাদ!
নিকু স্টির্ককা

এটি সেরা উত্তর। double Sample::*অংশ কী হয়!
ইয়াল

37

আপনি পরে এই সদস্যের অ্যাক্সেস করতে পারেন, উপর কোন উদাহরণস্বরূপ:

int main()
{    
  int Car::*pSpeed = &Car::speed;    
  Car myCar;
  Car yourCar;

  int mySpeed = myCar.*pSpeed;
  int yourSpeed = yourCar.*pSpeed;

  assert(mySpeed > yourSpeed); // ;-)

  return 0;
}

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

সাধারণত ইন্টারফেস (সি ++ এর বিশুদ্ধ বেস ক্লাস) ব্যবহার করা আরও ভাল ডিজাইনের পছন্দ।


তবে অবশ্যই এটি কি খারাপ অভ্যাস? youcar.setspeed (mycar.getpspeed) এর মতো কিছু করা উচিত
thecoshman

9
@ থেকোশম্যান: সম্পূর্ণরূপে নির্ভর করে - সেট / গেট পদ্ধতির পিছনে ডেটা সদস্যদের আড়াল করা এনক্যাপসুলেশন নয় এবং কেবল ইন্টারফেস বিমূর্তিতে মিল্মমাইডস প্রচেষ্টা। অনেক পরিস্থিতিতে, জনগণের কাছে "অস্বীকৃতি" যুক্তিসঙ্গত পছন্দ is তবে সেই আলোচনা সম্ভবত মন্তব্য কার্যকারিতার সীমা ছাড়িয়ে গেছে।
পিটারচেন

4
চিহ্নিত করার জন্য +1, যদি আমি সঠিকভাবে বুঝতে পারি যে এটি যে কোনও উদাহরণের সদস্যের পক্ষে একটি পয়েন্টার, এবং একটি উদাহরণের নির্দিষ্ট মানটির পয়েন্টার নয়, যা আমি সম্পূর্ণরূপে অনুপস্থিত ছিলাম।
জনবেকার

@ ফেলোশি আপনি সঠিকভাবে বুঝতে পারবেন :) (উত্তরে এটি জোর দিয়েছিলেন)।
পিটারচেন

26

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

  int Car::*pSpeed = &Car::speed;
  Car mycar;
  mycar.*pSpeed = 65;

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


আপনি একটি কোড স্নিপেট উদাহরণ ভাগ করতে পারেন যেখানে এই নির্মাণটি কার্যকর? ধন্যবাদ।
আশ্বিন নানজাপ্পা

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

19

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

#include <list>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>


class Car {
public:
    Car(int s): speed(s) {}
    void drive() {
        std::cout << "Driving at " << speed << " km/h" << std::endl;
    }
    int speed;
};

int main() {

    using namespace std;
    using namespace boost::lambda;

    list<Car> l;
    l.push_back(Car(10));
    l.push_back(Car(140));
    l.push_back(Car(130));
    l.push_back(Car(60));

    // Speeding cars
    list<Car> s;

    // Binding a value to a member variable.
    // Find all cars with speed over 60 km/h.
    remove_copy_if(l.begin(), l.end(),
                   back_inserter(s),
                   bind(&Car::speed, _1) <= 60);

    // Binding a value to a member function.
    // Call a function on each car.
    for_each(s.begin(), s.end(), bind(&Car::drive, _1));

    return 0;
}

11

দ্বৈত, নামযুক্ত-সদস্য (iexdata) এবং অ্যারে-সাবস্ক্রিপ্ট (অর্থাত্ [x [idx]) ইন্টারফেস সক্ষম করতে আপনি (সমজাতীয়) সদস্য ডেটাতে পয়েন্টারের একটি অ্যারে ব্যবহার করতে পারেন।

#include <cassert>
#include <cstddef>

struct vector3 {
    float x;
    float y;
    float z;

    float& operator[](std::size_t idx) {
        static float vector3::*component[3] = {
            &vector3::x, &vector3::y, &vector3::z
        };
        return this->*component[idx];
    }
};

int main()
{
    vector3 v = { 0.0f, 1.0f, 2.0f };

    assert(&v[0] == &v.x);
    assert(&v[1] == &v.y);
    assert(&v[2] == &v.z);

    for (std::size_t i = 0; i < 3; ++i) {
        v[i] += 1.0f;
    }

    assert(v.x == 1.0f);
    assert(v.y == 2.0f);
    assert(v.z == 3.0f);

    return 0;
}

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

2
@ ডোয়েনরোবিনসন কিন্তু unionসেই ফ্যাশনে টাইপ- পুং ব্যবহার করার বিষয়টি স্ট্যান্ডার্ড দ্বারা অনুমোদিত নয় কারণ এটি বিভিন্ন ধরণের অপরিজ্ঞাত আচরণের জন্য আহ্বান জানায় ... যদিও এই উত্তরটি ঠিক আছে।
আন্ডারস্কোর_২

এটি একটি ঝরঝরে উদাহরণ তবে অপারেটর [] পয়েন্টার-টু-কম্পোনেন্ট ছাড়াই পুনরায় লেখা যেতে পারে: float *component[] = { &x, &y, &z }; return *component[idx];অর্থাত পয়েন্টার-টু-কন্টেন্টটি অবর্ণন ব্যতীত কোনও উদ্দেশ্য করে না।
tobi_s

2

একটি উপায় আমি এটি ব্যবহার করেছি যদি আমার কাছে ক্লাসে কীভাবে কিছু করা যায় তার দুটি বাস্তবায়ন হয় এবং আমি নিয়মিত একটি বিবৃতিতে না গিয়ে রান-টাইমে একটি বেছে নিতে চাই ie

class Algorithm
{
public:
    Algorithm() : m_impFn( &Algorithm::implementationA ) {}
    void frequentlyCalled()
    {
        // Avoid if ( using A ) else if ( using B ) type of thing
        (this->*m_impFn)();
    }
private:
    void implementationA() { /*...*/ }
    void implementationB() { /*...*/ }

    typedef void ( Algorithm::*IMP_FN ) ();
    IMP_FN m_impFn;
};

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


মূলত, আপনি বিমূর্ত Algorithmএবং দুটি উদ্ভূত শ্রেণীর সাথে যেমন অর্জন করতে পারেন , যেমন, AlgorithmAএবং AlgorithmB। এই জাতীয় ক্ষেত্রে উভয় অ্যালগরিদমগুলি ভালভাবে পৃথক হয়ে গেছে এবং স্বতন্ত্রভাবে পরীক্ষা করা নিশ্চিত করা হয়।
shycha

2

ক্লাসগুলিতে পয়েন্টারগুলি আসল পয়েন্টার নয়; একটি শ্রেণি একটি যৌক্তিক গঠন এবং স্মৃতিতে কোনও শারীরিক অস্তিত্ব থাকে না, তবে, আপনি যখন কোনও শ্রেণীর সদস্যকে পয়েন্টার তৈরি করেন তখন এটি সদস্যের শ্রেণীর একটি অবজেক্টে অফসেট দেয় যেখানে সদস্যটি পাওয়া যায়; এটি একটি গুরুত্বপূর্ণ উপসংহার দেয়: যেহেতু স্থিতিশীল সদস্যরা কোনও বস্তুর সাথে সম্পর্কিত না তাই কোনও সদস্যের পয়েন্টারটি কোনও স্থির সদস্যের (ডেটা বা ফাংশন) নির্দেশ করতে পারে না যা নিম্নলিখিত বিবেচনা করে:

class x {
public:
    int val;
    x(int i) { val = i;}

    int get_val() { return val; }
    int d_val(int i) {return i+i; }
};

int main() {
    int (x::* data) = &x::val;               //pointer to data member
    int (x::* func)(int) = &x::d_val;        //pointer to function member

    x ob1(1), ob2(2);

    cout <<ob1.*data;
    cout <<ob2.*data;

    cout <<(ob1.*func)(ob1.*data);
    cout <<(ob2.*func)(ob2.*data);


    return 0;
}

উত্স: সম্পূর্ণ রেফারেন্স সি ++ - হারবার্ট শিল্ড চতুর্থ সংস্করণ


0

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


0

এখানে একটি উদাহরণ যেখানে ডেটা সদস্যদের নির্দেশক কার্যকর হতে পারে:

#include <iostream>
#include <list>
#include <string>

template <typename Container, typename T, typename DataPtr>
typename Container::value_type searchByDataMember (const Container& container, const T& t, DataPtr ptr) {
    for (const typename Container::value_type& x : container) {
        if (x->*ptr == t)
            return x;
    }
    return typename Container::value_type{};
}

struct Object {
    int ID, value;
    std::string name;
    Object (int i, int v, const std::string& n) : ID(i), value(v), name(n) {}
};

std::list<Object*> objects { new Object(5,6,"Sam"), new Object(11,7,"Mark"), new Object(9,12,"Rob"),
    new Object(2,11,"Tom"), new Object(15,16,"John") };

int main() {
    const Object* object = searchByDataMember (objects, 11, &Object::value);
    std::cout << object->name << '\n';  // Tom
}

0

ধরুন আপনার কাঠামো আছে সেই কাঠামোর অভ্যন্তরে রয়েছে * কিছু ধরণের নাম * একই ধরণের দুটি ভেরিয়েবল তবে ভিন্ন অর্থ সহ

struct foo {
    std::string a;
    std::string b;
};

ঠিক আছে, এখন বলুন যে আপনার fooএকটি পাত্রে একগুচ্ছ গুলি রয়েছে:

// key: some sort of name, value: a foo instance
std::map<std::string, foo> container;

ঠিক আছে, এখন ধরুন আপনি পৃথক উত্স থেকে ডেটা লোড করেছেন, তবে ডেটা একই ফ্যাশনে উপস্থাপন করা হয়েছে (উদাহরণস্বরূপ, আপনার একই পার্সিং পদ্ধতি দরকার)।

আপনি এরকম কিছু করতে পারেন:

void readDataFromText(std::istream & input, std::map<std::string, foo> & container, std::string foo::*storage) {
    std::string line, name, value;

    // while lines are successfully retrieved
    while (std::getline(input, line)) {
        std::stringstream linestr(line);
        if ( line.empty() ) {
            continue;
        }

        // retrieve name and value
        linestr >> name >> value;

        // store value into correct storage, whichever one is correct
        container[name].*storage = value;
    }
}

std::map<std::string, foo> readValues() {
    std::map<std::string, foo> foos;

    std::ifstream a("input-a");
    readDataFromText(a, foos, &foo::a);
    std::ifstream b("input-b");
    readDataFromText(b, foos, &foo::b);
    return foos;
}

এই মুহুর্তে, কলিং readValues()"ইনপুট-এ" এবং "ইনপুট-বি" এর সমন্বিত একটি পাত্রে ফেরত দেবে; সমস্ত কী উপস্থিত থাকবে এবং foos এর সাথে একটি বা খ বা উভয়ই থাকবে।


0

@ আননের & @ ওক্টালিস্টের উত্তরের জন্য কেবল কিছু ব্যবহারের কেস যুক্ত করতে এখানে পয়েন্টার-থেকে-সদস্য-কার্য এবং পয়েন্টার-থেকে-সদস্য-ডেটা সম্পর্কে একটি দুর্দান্ত পঠন সামগ্রী।

https://www.dre.vanderbilt.edu/~schmidt/PDF/C++-ptmf4.pdf


লিঙ্কটি মারা গেছে। সে কারণেই এখানে লিঙ্ক-কেবল উত্তরগুলি আশা করা যায় না। কমপক্ষে লিঙ্কটির সামগ্রীর সংক্ষিপ্তসার করুন, অন্যথায় আপনার উত্তরটি অবৈধ হয়ে যায় যখন লিঙ্কটি
দণ্ডিত হয়
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.