সি ++ এ "এক্স কোনও ধরণের নাম দেয় না" error


123

আমার নীচে দুটি ক্লাস ঘোষিত হয়েছে:

class User
{
public:
  MyMessageBox dataMsgBox;
};

class MyMessageBox
{
public:
  void sendMessage(Message *msg, User *recvr);
  Message receiveMessage();
  vector<Message> *dataMessageList;
};

আমি যখন জিসিসি ব্যবহার করে এটি সংকলন করার চেষ্টা করি তখন এটি নিম্নলিখিত ত্রুটিটি দেয়:

মাইমেসেজবক্স কোনও প্রকারের নাম দেয় না


16
অন্তহীন সময়ে আমি এই ত্রুটিটি
ঘটিয়েছি

1
নোট করুন যে আপনি ক্লাস সংজ্ঞায়নের আগে একটি .h / .hpp ফাইলে কোনও ঘোষণার জন্য বাহ্যিক রেফারেন্স রাখলে আপনিও এই ত্রুটিটি পেতে পারেন, এমনকি আপনি .c / .hpp অন্তর্ভুক্তির পরে প্রকৃত ঘোষণা থাকা সত্ত্বেও। ফাইল।
আউল

আপনার কমান্ড দিয়ে সি ++ ফাইলগুলি সর্বদা সংকলন করা উচিত g++এবং নাgcc
লোরেঞ্জো বাটিলোচি

উত্তর:


203

যখন সংকলক ক্লাসটি সংকলন করে Userএবং MyMessageBoxলাইনে পৌঁছায় MyMessageBoxতখনো সংজ্ঞায়িত করা হয়নি। সংকলকটির কোনও ধারণা MyMessageBoxনেই, সুতরাং আপনার শ্রেণীর সদস্যটির অর্থ বুঝতে পারি না।

সদস্য হিসাবে ব্যবহার করার আগে আপনাকে অবশ্যই MyMessageBoxএটি সংজ্ঞায়িত করা উচিত । এটি সংজ্ঞা আদেশের বিপরীতে সমাধান করা হয়। তবে আপনার একটি চক্রীয় নির্ভরতা রয়েছে: আপনি যদি উপরে চলে যান তবে নামের সংজ্ঞাটি সংজ্ঞায়িত হবে না!MyMessageBoxUserMyMessageBoxUser

আপনি যা করতে পারেন তা ঘোষণা করার জন্য User ; এটি, এটি ঘোষণা করুন কিন্তু এটি সংজ্ঞায়িত করবেন না। সংকলনের সময়, এমন এক ধরণের যা ঘোষিত কিন্তু সংজ্ঞায়িত না হয় তাকে অসম্পূর্ণ প্রকার বলে । সহজ উদাহরণ বিবেচনা করুন:

struct foo; // foo is *declared* to be a struct, but that struct is not yet defined

struct bar
{
    // this is okay, it's just a pointer;
    // we can point to something without knowing how that something is defined
    foo* fp; 

    // likewise, we can form a reference to it
    void some_func(foo& fr);

    // but this would be an error, as before, because it requires a definition
    /* foo fooMember; */
};

struct foo // okay, now define foo!
{
    int fooInt;
    double fooDouble;
};

void bar::some_func(foo& fr)
{
    // now that foo is defined, we can read that reference:
    fr.fooInt = 111605;
    fr.foDouble = 123.456;
}

এগিয়ে ঘোষণা করে User, MyMessageBoxএখনও এটি একটি পয়েন্টার বা রেফারেন্স গঠন করতে পারেন:

class User; // let the compiler know such a class will be defined

class MyMessageBox
{
public:
    // this is ok, no definitions needed yet for User (or Message)
    void sendMessage(Message *msg, User *recvr); 

    Message receiveMessage();
    vector<Message>* dataMessageList;
};

class User
{
public:
    // also ok, since it's now defined
    MyMessageBox dataMsgBox;
};

আপনি এটি অন্য উপায়ে করতে পারবেন না : যেমনটি উল্লেখ করা হয়েছে, কোনও শ্রেণীর সদস্যের একটি সংজ্ঞা থাকা দরকার। (কারণটি হ'ল সংকলকটি কতটা স্মৃতি Userগ্রহণ করে তা জানতে হবে এবং এটির এর সদস্যদের আকারটি জানা দরকার) এটি যদি আপনি বলতেন:

class MyMessageBox;

class User
{
public:
    // size not available! it's an incomplete type
    MyMessageBox dataMsgBox;
};

এটি কাজ করবে না, যেহেতু এটি আকারটি এখনও জানে না।


পার্শ্ব নোটে, এই ফাংশন:

 void sendMessage(Message *msg, User *recvr);

সম্ভবত পয়েন্টারের মাধ্যমে সেগুলির কোনওটি গ্রহণ করা উচিত নয়। আপনি কোনও বার্তা ছাড়াই কোনও বার্তা প্রেরণ করতে পারবেন না, বা কোনও ব্যবহারকারীকে এটি প্রেরণ করার জন্য আপনি কোনও বার্তা প্রেরণ করতে পারবেন না। এবং উভয় পরিস্থিতি উভয়ই প্যারামিটারের আর্গুমেন্ট হিসাবে নাল পাস করার মাধ্যমে স্পষ্ট হয় (নাল একটি পুরোপুরি বৈধ পয়েন্টার মান!)

বরং, একটি রেফারেন্স (সম্ভবত কনস্ট্যান্ড) ব্যবহার করুন:

 void sendMessage(const Message& msg, User& recvr);

3
+1 আজ কিছু শিখেছে - আমি ভেবেছিলাম এগিয়ে ঘোষণা MyMessageBoxকরা যথেষ্ট হবে। যদি MyMessageBoxটাইপের একটি ভেরিয়েবলও থাকে User- তবে এটি একটি অচলাবস্থা হবে?
আমারঘোষ

14
@ অমরগোশ: হ্যাঁ, এটা অসম্ভব হবে। যৌক্তিকরূপেও অসম্ভব, যেহেতু Userএকটি MessageBoxযা আছে তার একটি থাকবে User, যার একটি থাকবে MessageBoxযা থাকবে যা আছে Userযা আছে MessageBoxযা আছে Userযা আছে MessageBoxযা আছে User...
GManNickG


3

সি ++ সংকলকরা একবার তাদের ইনপুট প্রক্রিয়া করে। আপনার ব্যবহৃত প্রতিটি ক্লাস অবশ্যই প্রথমে সংজ্ঞায়িত করা উচিত। আপনি MyMessageBoxএটি সংজ্ঞায়িত করার আগে ব্যবহার করুন । এই ক্ষেত্রে, আপনি কেবল দুটি শ্রেণির সংজ্ঞাটি অদলবদল করতে পারেন।


সোয়াপিং যেমন কাজ করবে না MyMessageBoxহয়েছে Userএটা পদ্ধতি ঘোষণা টাইপ করুন।
অমরঘোষ

আসলে, এই সংজ্ঞা ক্লাস ব্যবহার করে না User। গুরুত্বপূর্ণ পার্থক্য, কারণ এর অর্থ শ্রেণি ব্যবহারকারী কেবলমাত্র সেই সময়ে ঘোষণা করা দরকার , সংজ্ঞায়িত নয় । তবে জিএমনের বিস্তৃত পোস্ট দেখুন।
MSalters 26'10

হ্যাঁ, তবে কেবল সংজ্ঞাটি অদলবদল করার কারণে Userপ্রকারটি এখনও ঘোষিত হয়নি।
আমারঘোষ

3

আপনাকে ব্যবহারকারীর আগে মাইমেজেজবক্সটি সংজ্ঞায়িত করতে হবে - কারণ ব্যবহারকারীর দ্বারা মাইমেজেজবক্সের অবজেক্টটি মান দ্বারা অন্তর্ভুক্ত করা হয় (এবং তাই সংকলকটির আকারটি জানা উচিত)।

এছাড়াও আপনাকে মাইমেজেজবক্সের জন্য ব্যবহারকারী হিসাবে ঘোষণা করতে হবে - কারণ মাইমেসেজবক্সে ব্যবহারকারী * প্রকারের সদস্য অন্তর্ভুক্ত রয়েছে।


3

সম্পর্কিত নোটে, যদি আপনার কাছে থাকে:

    class User; // let the compiler know such a class will be defined

    class MyMessageBox
    {
    public:
        User* myUser;
    };

    class User
    {
    public:
        // also ok, since it's now defined
        MyMessageBox dataMsgBox;
    };

তারপরে এটিও কাজ করবে, কারণ ব্যবহারকারী মাইমেসেজবক্সে পয়েন্টার হিসাবে সংজ্ঞায়িত হয়েছে


1
ফরোয়ার্ড ঘোষণাটি শব্দটি
বেনজিভ

1

প্রোটোটাইপ এটি ব্যবহারের আগে আপনাকে অবশ্যই ঘোষণা করতে হবে:

class User;

class MyMessageBox
{
public:
 void sendMessage(Message *msg, User *recvr);
 Message receiveMessage();
 vector<Message> *dataMessageList;
};

class User
{
public:
 MyMessageBox dataMsgBox;
};

সম্পাদনা করুন : ধরণের অদলবদল


1
না, কাজ করবে না। শ্রেণীর সদস্যদের অবশ্যই সংজ্ঞায়িত করা উচিত, জোর করে ঘোষণা করা হয়নি।
MSalters

1

এটি সর্বদা সি ++ তে উত্সাহিত হয় যে আপনার প্রতি শিরোনাম ফাইলের জন্য একটি শ্রেণি রয়েছে, এসও [ 1 ] এ এই আলোচনাটি দেখুন । GManNickG উত্তরের উত্তর কেন তা ঘটে তা বলে। তবে এটি সমাধানের সর্বোত্তম উপায় হ'ল Userএকটি হেডার ফাইল ( User.h) এবং MyMessageBoxঅন্য শিরোলেখ ফাইলটিতে শ্রেণি স্থাপন করা MyMessageBox.h। তারপরে আপনার User.hঅন্তর্ভুক্ত MyMessageBox.hএবং MyMessageBox.hআপনি অন্তর্ভুক্ত User.h। "গর্ডগুলি অন্তর্ভুক্ত করুন" [ 2 ] এ ভুলে যাবেন না যাতে আপনার কোডটি সফলভাবে সংকলন করে।

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