আমার সি ++ কোডে শ্রেণি নির্ভরতা কীভাবে সমাধান করবেন?


10

আমার সি ++ প্রকল্পে আমার দুটি ক্লাস রয়েছে Particleএবং Contact। ইন Particleবর্গ, আমি সদস্য পরিবর্তনশীল আছে std::vector<Contact> contactsযা এর সকল পরিচিতি রয়েছে Particleবস্তুর, এবং সংশ্লিষ্ট সদস্য ফাংশন getContacts()এবং addContact(Contact cont)। সুতরাং, "পার্টিকেল.এইচ" তে, আমি "পরিচিতি।" অন্তর্ভুক্ত করেছি।

ইন Contactবর্গ, আমি কোডের জন্য কন্সট্রাকটর যোগ করতে চাই Contactযে ডাকব Particle::addContact(Contact cont)যাতে, contactsউভয়ের জন্য আপডেট করা হয় Particleবস্তু যার মধ্যে Contactঅবজেক্ট যোগ করা হচ্ছে। সুতরাং, আমি "পরিচিতি.পি.পি" "পার্টিকাল.এইচ" অন্তর্ভুক্ত করতে হবে।

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


এই ক্লাসগুলি এমন একটি Networkশ্রেণীর সাথে একত্রে আবদ্ধ হবে যাতে এন কণা ( std::vector<Particle> particles) এবং এনসি পরিচিতি ( std::vector<Contact> contacts) থাকবে। তবে আমি particles[0].getContacts()যেমন ফাংশনগুলি সক্ষম করতে সক্ষম হয়েছি - Particleএই ক্ষেত্রে ক্লাসে এই জাতীয় ফাংশনগুলি রাখা কি ঠিক আছে , বা এই উদ্দেশ্যে সি ++ তে আরও ভাল "কাঠামো" রয়েছে (দুটি শ্রেণীর অন্য শ্রেণিতে ব্যবহৃত হচ্ছে) ।


আমি কীভাবে এটি কাছে আসছি তাতে আমার এখানে একটি দৃষ্টিকোণ স্থানান্তর দরকার। যেহেতু দুটি শ্রেণি একটি Networkশ্রেণীর অবজেক্টের মাধ্যমে সংযুক্ত , তাই কি সাধারণ কোড / শ্রেণি সংস্থার সাথে যোগাযোগের তথ্য সম্পূর্ণরূপে Networkঅবজেক্ট দ্বারা নিয়ন্ত্রিত রাখা হয় (যাতে কোনও কণা বিষয়টিকে তার পরিচিতি সম্পর্কে সচেতন না হওয়া উচিত এবং ফলস্বরূপ, এটির getContacts()সদস্য না হওয়া উচিত) ফাংশন)। তারপরে, একটি নির্দিষ্ট কণার কী পরিচিতি রয়েছে তা জানতে, আমার সেই তথ্যটি Network(যেমন, ব্যবহার করে network.getContacts(Particle particle)) মাধ্যমে প্রাপ্ত করা দরকার ।

কোনও কণা অবজেক্টের জন্য সেই জ্ঞানটিও কম (সাধারণভাবে নিরুৎসাহিত) সি ++ বর্গ নকশার পাশাপাশি (যেমন, সেই তথ্যটি অ্যাক্সেস করার একাধিক উপায় থাকতে পারে - নেটওয়ার্ক অবজেক্ট বা পার্টিকাল অবজেক্টের মাধ্যমে, যে কোনওটিকে আরও সুবিধাজনক বলে মনে হয়) )?


4
সিপ্পকন 2017 থেকে এখানে একটি আলোচনা রয়েছে - শিরোনামের তিন স্তর: youtu.be/su9ittf-ozk
রবার্ট অ্যান্ড্রেজুক

3
"সেরা," "আরও ভাল" এবং "গ্রহণযোগ্য" এর মতো শব্দগুলি যে প্রশ্নগুলিতে থাকে সেগুলি যদি আপনার মূল্যায়নের নির্দিষ্ট মানদণ্ডটি
রবার্ট হার্ভে

সম্পাদনার জন্য ধন্যবাদ, যদিও আপনার শব্দটিকে "সাধারণ" হিসাবে পরিবর্তন করা ঠিক এটি জনপ্রিয়তার প্রশ্নে পরিণত করে। কোডিং এক বা অন্য উপায়ে পরিচালিত হওয়ার কারণ রয়েছে এবং জনপ্রিয়তা ইঙ্গিত হতে পারে যে কোনও কৌশল "ভাল" ("ভাল" এর কিছু সংজ্ঞার জন্য), এটি কার্গো-কাল্টিংয়ের ইঙ্গিতও হতে পারে।
রবার্ট হার্ভে

@ রবার্ট হার্ভে আমি আমার চূড়ান্ত বিভাগে "আরও ভাল" এবং "খারাপ" সরিয়েছি। আমি মনে করি আপনি যখন Networkক্লাস অবজেক্টে Particleঅবজেক্ট এবং Contactঅবজেক্টস রাখেন তখন আমি সাধারণত (সম্ভবত পছন্দসই / উত্সাহিত) পদ্ধতির জন্য জিজ্ঞাসা করছি । এই বেস জ্ঞানের সাথে, আমি তখন আমার নির্দিষ্ট প্রয়োজনগুলির সাথে এটি খাপ খায় কিনা তা যাচাই করার চেষ্টা করতে পারি, যেগুলি এখনও প্রকল্পে যাওয়ার সময় অন্বেষণ / বিকাশাধীন।
আনইনকায়ারিংমাইন্ড

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

উত্তর:


17

আপনার প্রশ্নের দুটি অংশ আছে।

প্রথম অংশটি হ'ল সি ++ হেডার ফাইল এবং উত্স ফাইলগুলির সংগঠন। ফরোয়ার্ড ডিক্লেয়ারেশন এবং ক্লাস ডিক্লোরেশন (তাদের হেডার ফাইলে রেখে) এবং পদ্ধতি বডি (তাদের উত্স ফাইলে রেখে) ব্যবহার করে এটি সমাধান করা হয় । তদ্ব্যতীত, কিছু কিছু ক্ষেত্রে কঠিন কেস সমাধানের জন্য কেউ পিম্পল আইডিয়ম ("প্রয়োগের দিকে নির্দেশক") প্রয়োগ করতে পারেন । শেয়ারড-মালিকানা পয়েন্টার ( shared_ptr), একক-মালিকানা পয়েন্টার ( unique_ptr), এবং নন-মালিকানা পয়েন্টার (কাঁচা পয়েন্টার, অর্থাত্ "তারকাচিহ্ন") সেরা অনুশীলন অনুসারে ব্যবহার করুন।

দ্বিতীয় অংশটি হ'ল গ্রাফ আকারে আন্তঃসম্পর্কিত বস্তুগুলিকে কীভাবে মডেল করা যায় । সাধারণ গ্রাফগুলি যা ড্যাগগুলি নয় (নির্দেশিত অ্যাসাইক্লিক গ্রাফগুলি) গাছের মতো মালিকানা প্রকাশের প্রাকৃতিক উপায় নেই। পরিবর্তে, নোড এবং সংযোগগুলি সমস্ত মেটাডেটা যা একক গ্রাফ অবজেক্টের অন্তর্ভুক্ত। এক্ষেত্রে নোড-সংযোগের সম্পর্ককে সমষ্টি হিসাবে মডেল করা সম্ভব নয়। নোডগুলি সংযোগের "নিজস্ব" নয়; সংযোগগুলি নোডগুলির "নিজস্ব" নয়। পরিবর্তে, তারা সমিতি এবং উভয় নোড এবং সংযোগগুলি গ্রাফের "মালিকানাধীন" are গ্রাফটি কোয়েরি এবং ম্যানিপুলেশন পদ্ধতিগুলি সরবরাহ করে যা নোড এবং সংযোগগুলিতে কাজ করে।


উত্তরের জন্য ধন্যবাদ! আমার আসলে একটি নেটওয়ার্ক ক্লাস আছে যাতে এন কণা এবং এনসি পরিচিতি থাকবে। তবে আমি যেমন ফাংশনগুলি সক্ষম করতে চেয়েছিলাম particles[0].getContacts()- আপনি কি আপনার শেষ অনুচ্ছেদে পরামর্শ দিচ্ছেন যে আমার Particleক্লাসে এই জাতীয় ফাংশন না থাকা উচিত , বা বর্তমান কাঠামো ঠিক আছে কারণ সেগুলি সহজাতভাবে সম্পর্কিত / যুক্ত Network? এক্ষেত্রে সি ++ এর চেয়ে আরও ভাল সমিতি "কাঠামো" আছে কি?
আনইনকায়ারিংমাইন্ড

1
সাধারণত যে নেটওয়ার্ক অবজেক্টের মধ্যে সম্পর্ক সম্পর্কে জানার জন্য দায়বদ্ধ। আপনি যদি একটি সংলগ্ন তালিকা ব্যবহার করেন, উদাহরণস্বরূপ, কণার যোগাযোগগুলির সূচকগুলির সাথে network.particle[p]একটি network.contacts[p]মিল থাকবে । অন্যথায়, নেটওয়ার্ক এবং কণা একরকম উভয়ই একই তথ্য ট্র্যাক করছে।
বেহুদা

@ ব্যবহারহীন হ্যাঁ, সেখানেই আমি কীভাবে এগিয়ে যাব সে সম্পর্কে আমি নিশ্চিত নই। সুতরাং আপনি বলছেন যে Particleঅবজেক্টটি তার পরিচিতিগুলি সম্পর্কে সচেতন হওয়া উচিত নয় (সুতরাং আমার কোনও getContacts()সদস্য ফাংশন থাকা উচিত নয় ), এবং সেই তথ্যটি কেবলমাত্র Networkঅবজেক্টের মধ্যে থেকে আসা উচিত ? কোনও Particleঅবজেক্টের সেই জ্ঞান থাকা (যেমন, Networkবস্তু বা Particleবস্তুর যেকোন উপায়ে সুবিধাজনক বলে মনে হয় - সেই তথ্যটি অ্যাক্সেস করার একাধিক উপায় থাকতে পারে) তা কি খারাপ সি ++ শ্রেণির নকশা হতে পারে ? পরেরটি আমার কাছে আরও বোধগম্য মনে হয়, তবে সম্ভবত আমার এ সম্পর্কে আমার দৃষ্টিভঙ্গি বদলাতে হবে।
আনইনকায়ারিংমাইন্ড

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

@ সিএইচও ঠিক আছে, এটি বোধগম্য হয়। সুতরাং Particleএবং Contactসম্পূর্ণ পৃথক হওয়া উচিত, এবং তাদের মধ্যে সংযোগটি Networkবস্তু দ্বারা সংজ্ঞায়িত করা হয় । পুরোপুরি নিশ্চিত হওয়ার জন্য, এটি সম্ভবত (সম্ভবত) @ রওং যখন লেখেন, "নোড এবং সংযোগ উভয়ই গ্রাফের" মালিকানাধীন The ঠিক আছে?
আনইনকায়ারিংমাইন্ড

5

যদি আমি আপনাকে সঠিকভাবে বুঝতে পারি তবে একই পরিচিতি অবজেক্টটি একাধিক কণা অবজেক্টের অন্তর্ভুক্ত, যেহেতু এটি দুটি বা আরও বেশি কণার মধ্যে কোনও ধরণের শারীরিক যোগাযোগের প্রতিনিধিত্ব করে, তাই না?

সুতরাং প্রথম জিনিসটি যা আমি প্রশ্নবিদ্ধ বলে মনে করি তা কেন Particleএকটি সদস্যের পরিবর্তনশীল std::vector<Contact>? এটি একটি std::vector<Contact*>বা std::vector<std::shared_ptr<Contact> >পরিবর্তে হওয়া উচিত । addContactতারপরে addContact(Contact *cont)বা addContact(std::shared_ptr<Contact> cont)তার পরিবর্তে আলাদা স্বাক্ষর থাকা উচিত ।

এটি "পার্টিকেল.চ." এর "কন্টাক্ট.এইচ" অন্তর্ভুক্ত করা অপ্রয়োজনীয় করে তোলে, "পার্টিকেল। एच" এর একটি অগ্রণী ঘোষণা class Contactএবং "পার্টিকেল.পি.পি" "" যোগাযোগ.এইচ "অন্তর্ভুক্ত করা যথেষ্ট হবে।

তারপরে কনস্ট্রাক্টর সম্পর্কে প্রশ্ন। আপনি কিছু চান

 Contact(Particle &p1, Particle &p2)
 {
      p1.addContact(this);
      p2.addContact(this);
 }

রাইট? এই নকশাটি ঠিক আছে, যতক্ষণ না আপনার প্রোগ্রামটি যোগাযোগের অবজেক্ট তৈরি করতে হয় এমন সময়ে সময়ে সম্পর্কিত কণাগুলি সর্বদা জানে।

দ্রষ্টব্য, আপনি যদি এই std::vector<Contact*>পথে যান তবে আপনাকে আধ্যাত্মিক জীবনের আজীবন এবং মালিকানা সম্পর্কে কিছু চিন্তাভাবনা বিনিয়োগ করতে হবে Contact। কোনও কণা তার পরিচিতিগুলির "মালিকানাধীন" নয়, কোনও যোগাযোগ সম্ভবত তখনই মুছতে হবে যদি উভয় সম্পর্কিত Particleবস্তু ধ্বংস হয়। std::shared_ptr<Contact>পরিবর্তে ব্যবহার করা আপনার জন্য স্বয়ংক্রিয়ভাবে এই সমস্যার সমাধান করবে। অথবা আপনি কোনও "পার্শ্ববর্তী প্রসঙ্গ" অবজেক্টটিকে কণা এবং পরিচিতিগুলির মালিকানা নিতে চান (যেমন @ রওয়ং প্রস্তাবিত) এবং তাদের জীবনকাল পরিচালনা করে।


আমি addContact(const std::shared_ptr<Contact> &cont)ওভারের সুবিধা দেখছি না addContact(std::shared_ptr<Contact> cont)?
কালেথ

@Caleth: এই এখানে আলোচনা করা হয়েছে: stackoverflow.com/questions/3310737/... - "const" সত্যিই গুরুত্বপূর্ণ এখানে নয়, কিন্তু (মান দ্বারা এবং scalars) রেফারেন্স দ্বারা বস্তু ক্ষণস্থায়ী সি মান বাগ্ধারা হয় ++,।
ডক ব্রাউন

2
এই উত্তরগুলির মধ্যে অনেকগুলি পূর্ব- moveদৃষ্টান্ত থেকে বলে মনে হচ্ছে
কালেথ

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

1
@ ফিজিক্স কোডিং এথুশিয়াসট: না, এটি দুটি এবং দুটি ভিন্ন বস্তুর মধ্যে নয় এবং একই সাথে শারীরিক যোগাযোগের প্রতিনিধিত্ব করে একই বস্তুটি সরবরাহ particle1.getContacts()এবং particle2.getContacts()সরবরাহ করার ক্ষেত্রে সর্বাগ্রে । অবশ্যই, কেউ একই পদ্ধতিতে সিস্টেমটি ডিজাইনের চেষ্টা করতে পারে তবে একই শারীরিক যোগাযোগের প্রতিনিধিত্ব করে একই সাথে দুটি বস্তু পাওয়া যায় কিনা তা বিবেচ্য নয় । এটি অপরিবর্তনীয় করতে জড়িত হবে , তবে আপনি কি নিশ্চিত যে এটিই চান? Contactparticle1particle2ContactContact
ডক ব্রাউন

0

হ্যাঁ, আপনি যা বর্ণনা করেছেন তা হ'ল এটি নিশ্চিত করার একটি খুব গ্রহণযোগ্য উপায় যা প্রতিটি Contactউদাহরণ একটি এর পরিচিতির তালিকায় রয়েছে Particle


উত্তরের জন্য ধন্যবাদ. আমি কিছু পরামর্শ পড়েছিলাম যে পরস্পর নির্ভরশীল ক্লাসগুলির একজোড়া হওয়া এড়ানো উচিত (উদাহরণস্বরূপ, এমএস জোশীর "সি ++ ডিজাইনের প্যাটার্নস এবং ডেরিভেটিভস প্রাইসিং" তে) তবে আপাতদৃষ্টিতে এটি সঠিকভাবে হয় না? কৌতূহলের বাইরে, পারস্পরিক নির্ভরতার প্রয়োজন ছাড়াই সম্ভবত এই স্বয়ংক্রিয় আপডেটটি প্রয়োগের অন্য কোনও উপায় আছে?
আনইনকায়ারিংমাইন্ড

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

0

আপনি যা করেছেন তা সঠিক।

অন্য উপায় ... লক্ষ্য যদি প্রতিটি Contactতালিকায় রয়েছে তা নিশ্চিত করা , তবে আপনি এটি করতে পারেন:

  • Contact(প্রাইভেট কনস্ট্রাক্টর) ব্লক তৈরি ,
  • এগিয়ে Particleক্লাস ঘোষণা ,
  • করতে Particleএক বন্ধু বর্গ Contact,
  • মধ্যে Particleযা তৈরি করে একটি কারখানা পদ্ধতি তৈরিContact

তারপর আপনি অন্তর্ভুক্ত করতে হবে না particle.hcontact


উত্তরের জন্য ধন্যবাদ! এটি এটি কার্যকর করার একটি কার্যকর উপায় বলে মনে হচ্ছে। Networkক্লাস সম্পর্কিত প্রাথমিক প্রশ্নে আমার সম্পাদনাটি নিয়ে কেবল অবাক হয়েই ভাবছেন, এটি কি প্রস্তাবিত কাঠামোটিকে পরিবর্তন করে, বা এখনও এটি একই থাকবে?
আনইনকায়ারিংমাইন্ড

আপনি আপনার প্রশ্ন আপডেট করার পরে, এটি সুযোগ পরিবর্তন করছে। ... এখন আপনি আপনার অ্যাপ্লিকেশনটির আর্কিটেকচার সম্পর্কে জিজ্ঞাসা করছেন, আগে যখন এটি কোনও প্রযুক্তিগত সমস্যা ছিল।
রবার্ট অ্যান্ড্রেজুক

0

আপনি বিবেচনা করতে পারেন এমন আরও একটি বিকল্প হ'ল পরিচিতি কনস্ট্রাক্টর তৈরি করা যা কোনও পার্টিকেল রেফারেন্স টেম্প্লেটেড গ্রহণ করে। এটি কোনও পরিচিতিকে প্রয়োগ করে এমন কোনও ধারকটিতে নিজেকে যুক্ত করার অনুমতি দেবে addContact(Contact)

template<class Container>
Contact(/*parameters*/, Container& container)
{
  container.addContact(*this);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.