দু'জনকে একই ধরণের সমাধানকারী ক্লজগুলি কেন সিসিএসিতে অস্পষ্ট হিসাবে দেখা হয়


32

ক্লজ ব্যবহার করে আমার দুটি বেস ক্লাস রয়েছে

 class MultiCmdQueueCallback {
  using NetworkPacket  = Networking::NetworkPacket;
  ....
 }


 class PlcMsgFactoryImplCallback {
   using NetworkPacket = Networking::NetworkPacket;
  ....
 }

আমি তখন একটি ক্লাস ঘোষণা

class PlcNetwork : 
  public RouterCallback, 
  public PlcMsgFactoryImplCallback, 
  public MultiCmdQueueCallback {
  private:
    void sendNetworkPacket(const NetworkPacket &pdu);
}

সংকলকটি তখন 'নেটওয়ার্কপ্যাকেট'-এর একটি ত্রুটিযুক্ত রেফারেন্সটিকে দ্ব্যর্থহীন' সেন্ড নেটওয়ার্কপ্যাকেট (নেটওয়ার্কপ্যাকেট & ... ') হিসাবে চিহ্নিত করেছে

এখন উভয়ই 'ক্লজ ব্যবহার করছে' একই আন্ডারলাইং ক্লাস নেটওয়ার্কিংয়ের জন্য সমাধান: নেটওয়ার্কপ্যাককেট

এবং প্রকৃতপক্ষে যদি আমি পদ্ধতি ঘোষণার সাথে প্রতিস্থাপন করি:

 void sendNetworkPacket(const Networking::NetworkPacket &pdu);

এটা জরিমানা সংকলন।

উভয়ই একই অন্তর্নিহিত প্রকারের দিকে ইঙ্গিত করে যদিও সংকলক প্রতিটি ক্লজকে পৃথক প্রকার হিসাবে ব্যবহার করছে কেন? এটি কি স্ট্যান্ডার্ড দ্বারা বাধ্যতামূলক বা আমাদের একটি সংকলক বাগ রয়েছে?


এটি সংকলক যথেষ্ট চালাক নয় বলে মনে হচ্ছে
ইদ্রিস

এই মুহুর্তে এই NetworkPacketসংকলকটি হ'ল পয়েন্টটি কেবল জানে যে তিনটি বিদ্যমান রয়েছে - মাল্টিমিক্সএমকিউইউ ক্যালব্যাক, প্ল্যাকএমএসজিফ্যাক্ট্রিআইপলক্যালব্যাক, নেটওয়ার্কিং এ। কোনটি ব্যবহার করবেন তা নির্দিষ্ট করা উচিত। এবং আমি মনে করি না যে virtualএখানে রাখা কোনও উপকারে আসবে।
বুদ্ধিমানব্রো

@ আইড্রিস: পরিবর্তে, আপনি বোঝাচ্ছেন মান যথেষ্ট পরিমাণে অনুমোদিত নয়। সংকলক মান অনুসরণ করা ঠিক।
জারোড 42

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

বহু-উত্তরাধিকারের সমস্যাগুলির মধ্যে একটি
agগল 275

উত্তর:


28

উপন্যাসের ফলাফলের ধরণটি দেখার আগে (এবং অ্যাক্সেসযোগ্যতা)

আমরা নাম তাকান

এবং প্রকৃতপক্ষে,

NetworkPacket হতে পারে

  • MultiCmdQueueCallback::NetworkPacket
  • অথবা PlcMsgFactoryImplCallback::NetworkPacket

তারা উভয় যে বিষয়টি নির্দেশ করে Networking::NetworkPacketতা অপ্রাসঙ্গিক।

আমরা প্রথম নামটির রেজোলিউশন করি, যার ফলস্বরূপ অস্পষ্টতা।


প্রকৃতপক্ষে এটি কেবলমাত্র আংশিক সত্য যদি আমি প্ল্যাকনেট ওয়ার্কে একটি ব্যবহার যুক্ত করে: | নেটওয়ার্কপ্যাকেট = মাল্টিমিএমডিকিউ ক্যালব্যাক :: নেটওয়ার্কপ্যাককেট ব্যবহার করে; আমি একটি সংকলক ত্রুটি পেয়েছি কারণ পূর্ববর্তী ক্লজটি ব্যক্তিগত ছিল।
অ্যান্ড্রু Goedhart

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

আমার সমস্যাটি এখানে কেন বেস শ্রেণীর একটি ব্যক্তিগত নামকরণ ধারা থেকে নামটি প্রচার করা হচ্ছে। যদি আমি একটি ব্যক্তিগত ঘোষণাপত্র অপসারণ করি যেমন বেস
বেসগুলির একটিতে

1
অ্যান্ড্রুগয়েদার্ট নাম অনুসন্ধান (স্পষ্টতই) অ্যাক্সেসযোগ্যতা বিবেচনা করে না। আপনি যদি একটি জনসাধারণকে এবং অন্যজনকে ব্যক্তিগত তৈরি করেন তবে আপনি একই ত্রুটি পাবেন। এটি আবিষ্কার করা প্রথম ত্রুটি, সুতরাং এটি মুদ্রিত হওয়া প্রথম ত্রুটি। যদি আপনি একটি উপনাম অপসারণ করেন তবে অস্পষ্টতার সমস্যাটি চলে গেছে, তবে অনিবার্যতার একটিটি রয়ে গেছে, সুতরাং আপনি পরবর্তী ত্রুটিটি মুদ্রিত পাবেন। যাইহোক, একটি ভাল ত্রুটি বার্তা নয় (এমএসভিসি আরও একবার?), জিসিসি আরও: সম্পর্কে আরও সুনির্দিষ্ট error: [...] is private within this context
অ্যাকোনকাগুয়া

1
@ অ্যান্ড্রুগোয়েদার্ট নিম্নলিখিত বিষয়গুলি বিবেচনা করুন: class A { public: void f(char, int) { } private: void f(int, char) { } }; void demo() { A a; a.f('a', 'd'); }- একই নয়, তবে ওভারলোড রেজোলিউশনটি একইভাবে কাজ করে: যথাযথভাবে বাছাইয়ের পরে অ্যাক্সেসিবিলিটি বিবেচনা করে সমস্ত উপলব্ধ ফাংশন বিবেচনা করুন ... প্রদত্ত ক্ষেত্রে আপনি অস্পষ্টতাও পাবেন; যদি আপনি দুটি অক্ষর গ্রহণের জন্য প্রাইভেট ফাংশনটি পরিবর্তন করেন তবে এটি ব্যক্তিগত থাকাকালীন নির্বাচিত হবে - এবং আপনি পরবর্তী সংকলনের ত্রুটিতে চলেছেন।
অ্যাকোনকাগুয়া

14

আপনি কোনটি ব্যবহার করতে চান তা নিজেই নির্বাচন করে আপনি অস্পষ্টতার সমাধান করতে পারেন।

class PlcNetwork : 
  public RouterCallback, 
  public PlcMsgFactoryImplCallback, 
  public MultiCmdQueueCallback {

using NetworkPacket= PlcMsgFactoryImplCallback::NetworkPacket; // <<< add this line
private:
    void sendNetworkPacket(const NetworkPacket &pdu);

}

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

সংকলকটি কেবলমাত্র প্রথম ধাপে নামগুলি সন্ধান করে, সম্পূর্ণরূপে স্বতন্ত্র যদি এই নামটি কোনও ফাংশন, প্রকার, নাম, পদ্ধতি বা যাই হোক না কেন। নামগুলি অস্পষ্ট থাকলে সংকলক থেকে আর কোনও পদক্ষেপ নেওয়া হয় না! এটি কেবল ত্রুটি বার্তায় অভিযোগ করে থেমে যায়। সুতরাং প্রদত্ত ব্যবহারের বিবৃতি দিয়ে কেবল অস্পষ্টতাটি সমাধান করুন।


শব্দটি সম্পর্কে কিছু সন্দেহ আছে। যদি এটি সংজ্ঞাগুলি সন্ধান করে তবে তা কি সেই ধরণের পাশাপাশি বিবেচনা করবে না? এটি কি কেবল নামগুলি অনুসন্ধান করবে না (এবং কীভাবে সংজ্ঞায়িত করা হবে তা ভুলে যান )? মানটির কিছু রেফারেন্স দুর্দান্ত থাকবে ...
অ্যাকোনকাগুয়া

এই শেষ মন্তব্যটি কেন সঠিকভাবে ব্যাখ্যা করে । এই মন্তব্যটি দিয়ে শেষ অনুচ্ছেদটি প্রতিস্থাপন করুন এবং আমি উপস্থাপন করব;)
অ্যাকনকাগুয়া

আমি মেনে নিতে পারি না - আমি প্রশ্ন লেখক নই ... দুঃখিত যদি আমি আপনার স্নায়ু নিয়ে উঠতে পারি। কেবল উত্তরটি উন্নত করার চেষ্টা করছিলাম, যেমন আমি অনুভব করেছি যে এটি কিউএর মূল প্রশ্নের আগে উত্তর দেয়নি ...
অ্যাকনকাগুয়া

@ আঙ্কাকাগুয়া: উবস, আমার দোষ :-) উন্নতির জন্য ধন্যবাদ!
ক্লাউস

আসলে এটি কাজ করে না কারণ দুটি ক্লজ ব্যবহার করা ব্যক্তিগত using আমি যদি প্ল্যাকনেট ওয়ার্কে একটি ব্যবহার যুক্ত করি: | নেটওয়ার্কপ্যাকেট = মাল্টিমিএমডিকিউ ক্যালব্যাক :: নেটওয়ার্কপ্যাককেট ব্যবহার করে; আমি একটি সংকলক ত্রুটি পেয়েছি কারণ পূর্ববর্তী ক্লজটি ব্যক্তিগত ছিল। যাইহোক, আমি যদি ক্লজটিকে জনসাধারণ এবং অন্যটি ব্যক্তিগত ব্যবহার করে একটি বেস শ্রেণি তৈরি করি তবে আমি এখনও একটি দ্বিধাদ্বন্দ্বতা ত্রুটি পেয়েছি। বেস ক্লাসে সংজ্ঞায়িত নয় এমন পদ্ধতিগুলিতে আমি অস্পষ্টতা ত্রুটি পেয়েছি।
অ্যান্ড্রু Goedhart

8

ডক্স থেকে :

একটি টাইপ ওরফে ঘোষণার মাধ্যমে একটি নাম প্রবর্তিত হয় যা টাইপ-আইডি দ্বারা চিহ্নিত ধরণের প্রতিশব্দ হিসাবে ব্যবহৃত হতে পারে। এটি কোনও নতুন ধরণের পরিচিতি দেয় না এবং এটি বিদ্যমান টাইপ নামের অর্থ পরিবর্তন করতে পারে না।

যদিও, এই দুটি usingধারা একই ধরণের প্রতিনিধিত্ব করে, সংকলকটির নিম্নলিখিত পরিস্থিতিতে দুটি পছন্দ রয়েছে:

void sendNetworkPacket(const NetworkPacket &pdu);

এটি এর মধ্যে চয়ন করতে পারে:

  • MultiCmdQueueCallback::NetworkPacket এবং
  • PlcMsgFactoryImplCallback::NetworkPacket

কারণ এটি উভয় MultiCmdQueueCallbackএবং PlcMsgFactoryImplCallbackবেস শ্রেণী থেকে উত্তরাধিকারসূত্রে প্রাপ্ত । সংকলকটির নাম রেজোলিউশনের ফলস্বরূপ আপনার যে অস্পষ্টতা ত্রুটি। এটি সংশোধন করার জন্য, আপনাকে স্পষ্টভাবে সংকলকটিকে এক বা অন্যটিকে এর মতো ব্যবহার করতে নির্দেশ করতে হবে:

void sendNetworkPacket(const MultiCmdQueueCallback::NetworkPacket &pdu);

অথবা

void sendNetworkPacket(const PlcMsgFactoryImplCallback::NetworkPacket &pdu);

সত্যি কথা বলতে, আমি সন্তুষ্ট বোধ করি না ... তারা উভয়ই একই ধরণের প্রতিশব্দ। আমি সহজেই থাকতে পারি class C { void f(uint32_t); }; void C::f(unsigned int) { }(ওরফে ম্যাচগুলি সরবরাহ করে)) তাহলে এখানে কেন পার্থক্য? তারা এখনও একই ধরণের, আপনার উদ্ধৃতি দ্বারা নিশ্চিত হয়েছে (যা আমি ব্যাখ্যা করার পক্ষে যথেষ্ট বিবেচনা করি না) ...
অ্যাকনকাগুয়া

@ আঙ্কাকাগুয়া: বেস টাইপ বা উপন্যাসটি ব্যবহার করা কখনই কোনও তাত্পর্যপূর্ণ করে না। একটি উপনাম কখনই নতুন ধরণের হয় না। দুটি বেস ক্লাসে এসএমএ উরফ দিয়ে আপনি যে অস্পষ্টতা তৈরি করেছেন তার সাথে আপনার পর্যবেক্ষণের কোনও সম্পর্ক নেই।
ক্লাউস

1
@ আঙ্কাকাগুয়া আমার মনে হয় আপনি যে উদাহরণটি উল্লেখ করেছেন সেটি প্রশ্ন থেকে পরিস্থিতিটির জন্য সঠিক সমতুল্য নয়
নটক্র্যাকার

ঠিক আছে, আসুন কিছুটা পরিবর্তন করা যাক: এ, বি এবং সি এবং টাইপিডেফ ডি ক্লাসগুলির নাম দিন, তবে আপনি এমনকি করতে পারেন: class C : public A, public B { void f(A::D); }; void C::f(B::D) { }- কমপক্ষে জিসিসি গ্রহণ করে।
অ্যাকোনকাগুয়া

প্রশ্ন লেখক আক্ষরিক অর্থে জিজ্ঞাসা করেছিলেন 'সংকলক কেন প্রতিটি ক্লজকে পৃথক ধরণের হিসাবে ব্যবহার করছে যদিও তারা উভয়ই একই অন্তর্নিহিত প্রকারের দিকে ইঙ্গিত করে?' - এবং আমি দেখতে না কিভাবে তলব নির্মল হবে কেন , পরিবর্তে, এটা ঠিক QA তে এর বিভ্রান্তির নিশ্চিত ... কি বলতে উত্তর না চান ভুল , কিন্তু এটা আমার চোখে পর্যাপ্ত শোধন না .. ।
একনকাগুয়া

2

দুটি ত্রুটি রয়েছে:

  1. ব্যক্তিগত প্রকারের উপাধিতে অ্যাক্সেস করা
  2. প্রকারের উপন্যাসের বিষয়ে অস্পষ্ট রেফারেন্স

ব্যক্তিগত-ব্যক্তিগত

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

পাবলিক-সর্বজনীন

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

class MultiCmdQueueCallback {
    using NetworkPacketID  = size_t;
    // ...
};


class PlcMsgFactoryImplCallback {
    using NetworkPacketID = uint64_t;
    // ...
};

সংকলক উভয় NetworkPacketIDএকই আচরণ করা উচিত ? অবশ্যই না। কারণ 32-বিট সিস্টেমে size_t32-বিট দীর্ঘ এবং uint64_tসর্বদা 64-বিট থাকে। তবে আমরা যদি সংকলকটি অন্তর্নিহিত ডেটা প্রকারের জন্য যাচাই করতে চাই, তবে এটি 64-বিট সিস্টেমে থাকা ব্যক্তিদের মধ্যে পার্থক্য করতে পারে না।

প্রকাশ্য ব্যক্তিগত

আমি বিশ্বাস করি যে এই উদাহরণটি ওপির ব্যবহারের ক্ষেত্রে কোনও ধারণা রাখে না, তবে যেহেতু আমরা এখানে সাধারণভাবে সমস্যাগুলি সমাধান করছি, আসুন এটি বিবেচনা করুন:

class MultiCmdQueueCallback {
private:
    using NetworkPacket  = Networking::NetworkPacket;
    // ...
};

class PlcMsgFactoryImplCallback {
public:
    using NetworkPacket  = Networking::NetworkPacket;
    // ...
};

আমি মনে করি এই ক্ষেত্রে সংকলকটির PlcNetwork::NetworkPacketমতো আচরণ করা উচিত PlcMsgFactoryImplCallback::NetworkPacketকারণ এতে অন্য কোনও পছন্দ নেই। কেন এটি এখনও তা করতে অস্বীকৃতি জানায় এবং অস্পষ্টতার জন্য দোষ চাপিয়ে দেওয়া আমার কাছে একটি মিস্ট্রি।


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