ত্রুটি: এক্সএক্সএক্সএক্সএক্সএক্সএক্স কোয়ালিফায়ারদের 'এই' যুক্তি হিসাবে পাস করা passing


456
#include <iostream>
#include <set>

using namespace std;

class StudentT {

public:
    int id;
    string name;
public:
    StudentT(int _id, string _name) : id(_id), name(_name) {
    }
    int getId() {
        return id;
    }
    string getName() {
        return name;
    }
};

inline bool operator< (StudentT s1, StudentT s2) {
    return  s1.getId() < s2.getId();
}

int main() {

    set<StudentT> st;
    StudentT s1(0, "Tom");
    StudentT s2(1, "Tim");
    st.insert(s1);
    st.insert(s2);
    set<StudentT> :: iterator itr;
    for (itr = st.begin(); itr != st.end(); itr++) {
        cout << itr->getId() << " " << itr->getName() << endl;
    }
    return 0;
}

সঙ্গতিপূর্ণভাবে:

cout << itr->getId() << " " << itr->getName() << endl;

এটি একটি ত্রুটি দেয় যে:

../main.cpp:35: ত্রুটি: 'কনট স্টুডেন্টটি'কে' এই স্টুডেন্টটি 'এর' আর্গুমেন্ট হিসাবে পাস করা 'গেটআইডি ()' বাছাইযোগ্য

../main.cpp:35: ত্রুটি: 'স্ট্যান্ড স্ট্রিং স্টুডেন্টটি :: getName ()' কোয়ালিফায়ারকে ছাড়াই 'স্ট্যান্ড স্ট্রিং স্টুডেন্টটি' এর এই যুক্তি হিসাবে 'কনস্টেন্ট স্টুডেন্টটি' পাস করা

এই কোডটিতে কি সমস্যা আছে? ধন্যবাদ!


13
আপনার কোড স্নিপেটে লাইন 35 কোথায়?
সিলিকোতে

117
আমি আশা করি জিসিসি এই ত্রুটি বার্তাকে আরও উন্নত করবে, উদাহরণস্বরূপ "ছাড়পত্র কোয়ালিফায়ার" -> "ব্রেক
কনস্ট

13
@ জেফ্রিটজ ৪২: বাতিল হওয়া মামলার জন্য বিভ্রান্তিকর হবেvolatile
প্লাজমাএইচএইচ

3
@ প্লাজমাএইচ ত্রুটি বার্তাটি "ব্রেকস কনস্ট যথার্থতা" এবং "ব্রেক অস্থির নির্ভুলতা" এ বিভক্ত হবে। এখন, বেশিরভাগ লোকই
কোনও কিছুর উদ্বোধন

উত্তর:


523

এর মধ্যে থাকা বস্তুগুলি std::setসংরক্ষণ করা হয় const StudentT। সুতরাং আপনি যখন অবজেক্টটির getId()সাথে কল করার চেষ্টা করলেন তখন constসংকলকটি একটি সমস্যা সনাক্ত করে, মূলত আপনি কনস্ট কনট্রাক্টে নন-কনস্টের সদস্য ফাংশনটি কল করছেন যা অনুমোদিত নয় কারণ নন-কনস্টের সদস্য ফাংশনগুলি বস্তুটি সংশোধন না করার জন্য কোনও প্রতিশ্রুতি দেয় না; তাই সংকলকটি একটি নিরাপদ অনুমান করতে চলেছেgetId() যা অবজেক্টটি সংশোধন করার চেষ্টা করতে পারে তবে একই সাথে এটি লক্ষ্য করে যে অবজেক্টটি কনস্ট; সুতরাং কনস্ট কনটাকে সংশোধন করার যে কোনও প্রয়াস ত্রুটি হওয়া উচিত। সুতরাং সংকলক একটি ত্রুটি বার্তা উত্পন্ন করে।

সমাধানটি সহজ: ফাংশনগুলি এইভাবে তৈরি করুন:

int getId() const {
    return id;
}
string getName() const {
    return name;
}

এটি প্রয়োজনীয় কারণ এখন আপনি কল করতে পারেন getId()এবং getName()কনস্টেন্ট অবজেক্টগুলিকে হিসাবে:

void f(const StudentT & s)
{
     cout << s.getId();   //now okay, but error with your versions
     cout << s.getName(); //now okay, but error with your versions
}

সাইডেনোট হিসাবে, আপনার এই operator<হিসাবে প্রয়োগ করা উচিত :

inline bool operator< (const StudentT & s1, const StudentT & s2)
{
    return  s1.getId() < s2.getId();
}

নোটের প্যারামিটারগুলি এখন constরেফারেন্স।


3
এরকম স্পষ্ট ব্যাখ্যা। ধন্যবাদ। তবে আমি আপনার শেষ কোড স্নিপেট সম্পর্কে অবাক হই। কেন ফাংশন প্যারামিটারে রেফারেন্স ব্যবহার করবেন? const StudentT & s1, const StudentT & s2?
রাফায়েল আদেল

2
@ রাফায়েলএডেল: আপনি অপ্রয়োজনীয় অনুলিপি এড়ানোর জন্য রেফারেন্স ব্যবহার করেন এবং constকারণ ফাংশনটি অবজেক্টটি সংশোধন করার প্রয়োজন হয় না, তাই এটি constসংকলন-সময় এটিকে প্রয়োগ করে।
নওয়াজ

90

শ্রেণীর উদাহরণটি সংশোধন করে না এমন সদস্য ফাংশনগুলি এই হিসাবে ঘোষণা করা উচিত const:

int getId() const {
    return id;
}
string getName() const {
    return name;
}

যে কোনও সময় আপনি "ডিস্কার্ডস কোয়ালিফায়ার" দেখেন, এটি সম্পর্কে constবা কথা বলছে volatile


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

@ মাহেশ: হ্যাঁ, এটি দৃ const ়তা সংশোধনের অংশ । আমি এখান constথেকে আসছি সে সম্পর্কে আমি নিশ্চিত নই , তবে আমার সন্দেহ হয় setযে উদাহরণটি পরিবর্তন হতে এবং এর ফলে সেটটি অকার্যকরকরণ থেকে আটকাতে পুনরুক্তিদাতা থেকে একটি কনট রেফারেন্স ফিরে আসবে suspect
ফ্রেড লারসন

@ মাহেশ: আমার কোড পর্যালোচনা পাস করবেন না। আমার একজন সহকর্মী আছেন যিনি আমাকে "কনস্টেবল" হিসাবে উল্লেখ করেছেন। 8V) পরিবর্তন foo obj;করতে const foo obj;একবার এবং দেখুন সেখানে কি ঘটছে। বা একটি constরেফারেন্স পাস foo
ফ্রেড লারসন

3
@ মাহেশ: এটি আমি যেমন বলেছিলাম - এর মধ্যে উপাদানগুলি setপরিবর্তিত হলে আদেশটি বিচলিত হতে পারে এবং সেটটি আর বৈধ নয়। একটিতে map, কেবল কীটি const। একটিতে set, পুরো বস্তুটি সত্যই কী key
ফ্রেড লারসন

1
@ মাহেশ: কনস্ট প্রয়োজনীয়, অন্যথায় আপনি তাদেরকে কনট অবজেক্ট দিয়ে কল করতে পারবেন না। f()আমার উত্তর ফাংশন দেখুন ।
নওয়াজ

5

আসলে সি ++ স্ট্যান্ডার্ড (যেমন সি ++ 0 এক্স ড্রাফ্ট ) বলেছে (আমার কাছে এটি নির্দেশ করার জন্য টিএনএক্স @ জিওও ও @ বেন ভয়েগ্ট):

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

সুতরাং ভিসি ++ ২০০৮ ডিনকামওয়্যার বাস্তবায়ন ত্রুটিযুক্ত।


পুরানো উত্তর:

আপনি সেই ত্রুটিটি পেয়েছেন কারণ স্ট্যান্ড লিবের নির্দিষ্ট কিছু বাস্তবায়নে set::iteratorযেমন রয়েছে set::const_iterator

উদাহরণস্বরূপ libstdc ++ (g ++ দিয়ে পাঠানো) এর এটি রয়েছে ( পুরো উত্স কোডের জন্য এখানে দেখুন ):

typedef typename _Rep_type::const_iterator            iterator;
typedef typename _Rep_type::const_iterator            const_iterator;

এবং এসজিআইয়ের ডক্সে এটি উল্লেখ করেছে:

iterator       Container  Iterator used to iterate through a set.
const_iterator Container  Const iterator used to iterate through a set. (Iterator and const_iterator are the same type.)

অন্যদিকে ভিসি ++ ২০০ Express এক্সপ্রেস আপনার কোডটি কম্পাইল করে যে আপনি set::iteratorএস- তে নন কনস্ট পদ্ধতি ব্যবহার করছেন ।


2

আসুন আমি আরও বিস্তারিত উদাহরণ দেই। নীচের কাঠামো হিসাবে:

struct Count{
    uint32_t c;

    Count(uint32_t i=0):c(i){}

    uint32_t getCount(){
        return c;
    }

    uint32_t add(const Count& count){
        uint32_t total = c + count.getCount();
        return total;
    }
};

এখানে চিত্র বর্ণনা লিখুন

আপনি উপরের দেখতে হিসাবে, আইডিই (সিএলওন) টিপস দেবে Non-const function 'getCount' is called on the const object। পদ্ধতিতে add countকনস্টের অবজেক্ট হিসাবে ঘোষিত হয় তবে পদ্ধতিটি getCountকনস্ট পদ্ধতি নয়, সুতরাং count.getCount()সদস্যদের মধ্যে পরিবর্তন করতে পারেcount

নীচের মত সংকলন ত্রুটি (আমার সংকলকের মূল বার্তা):

error: passing 'const xy_stl::Count' as 'this' argument discards qualifiers [-fpermissive]

উপরের সমস্যা সমাধানের জন্য, আপনি:

  1. পদ্ধতি পরিবর্তন uint32_t getCount(){...}করার জন্য uint32_t getCount() const {...}। সুতরাং count.getCount()সদস্যদের পরিবর্তন করবেন না count

অথবা

  1. পরিবর্তন uint32_t add(const Count& count){...}করার জন্য uint32_t add(Count& count){...}। সুতরাং এতে countসদস্য পরিবর্তন করার বিষয়ে চিন্তা করবেন না।

আপনার সমস্যা হিসাবে, std :: সেটে অবজেক্টগুলি কনস্টেন্ট স্টুডেন্ট হিসাবে সংরক্ষণ করা হয় তবে পদ্ধতি getIdএবংgetName নয়, সুতরাং আপনি উপরের ত্রুটিটি দিন।

আপনি এই প্রশ্নটি দেখতে পারেন 'কনস্ট' এর অর্থ কোনও ক্লাসের কোনও কার্য ঘোষণায় শেষ? আরও বিশদ জন্য।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.