ক্লাস ভেরিয়েবল পাস করা কি কোনও খারাপ ধারণাটি কোনও শ্রেণি পদ্ধতি তৈরি করেছে?


14

আমি যা বলতে চাইছি তা এখানে:

class MyClass {
    int arr1[100];
    int arr2[100];
    int len = 100;

    void add(int* x1, int* x2, int size) {
        for (int i = 0; i < size; i++) {
            x1[i] += x2[i];
        }
    }
};

int main() {
    MyClass myInstance;

    // Fill the arrays...

    myInstance.add(myInstance.arr1, myInstance.arr2, myInstance.len);
}

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


13
যদি আপনি এটি করার মতো মনে করেন তবে এটি একটি খারাপ ডিজাইনের ইঙ্গিত দিচ্ছে। শ্রেণীর বৈশিষ্ট্যগুলি সম্ভবত অন্য কোথাও অন্তর্ভুক্ত।
বিটসফ্লোগিক

11
স্নিপেট খুব ছোট। মিশ্র বিমূর্তির এই স্তরটি এই আকারের স্নিপেটে ঘটে না। আপনি ডিজাইন বিবেচনার উপর কিছু ভাল পাঠ্য সঙ্গে এটি ঠিক করতে পারেন।
জোশুয়া

16
কেন আপনি এমনকি এটি করতে হবে তা আমি সত্যই বুঝতে পারি না। আপনি কি লাভ? কেন কেবল কোনও নন-আরগ addপদ্ধতি নেই যা সরাসরি তার অভ্যন্তরগুলিতে কাজ করে? শুধু কেন?
ইয়ান কেম্প

2
@ ইয়ানকেম্প বা এমন একটি addপদ্ধতি রয়েছে যা আর্গুমেন্ট গ্রহণ করে তবে একটি শ্রেণীর অংশ হিসাবে উপস্থিত হয় না। একসাথে দুটি অ্যারে যুক্ত করার জন্য খাঁটি ফাংশন।
কেভিন

অ্যাড পদ্ধতিটি কি সর্বদা arr1 এবং arr2 যুক্ত করে, বা এটি কোনও কিছুর যোগ করতে ব্যবহৃত হতে পারে?
ব্যবহারকারী 253751

উত্তর:


33

ক্লাসের সাথে এমন কিছু জিনিস থাকতে পারে যা আমি আলাদাভাবে করব তবে সরাসরি প্রশ্নের উত্তর দেওয়ার জন্য আমার উত্তর হবে

হ্যাঁ, এটি একটি খারাপ ধারণা

আমার এটির প্রধান কারণ হ'ল addফাংশনে যা যা পাস হবে তাতে আপনার কোনও নিয়ন্ত্রণ নেই । নিশ্চয়ই আপনি আশা করছেন এটি সদস্য সদস্যগুলির মধ্যে একটি, তবে কেউ যদি 100 এর চেয়ে কম আকারের একটি আলাদা অ্যারে পাস করে বা আপনি 100 এর চেয়ে বেশি দৈর্ঘ্যে পাস করেন তবে কী হবে?

যা ঘটে তা হ'ল আপনি বাফারকে ছাড়িয়ে যাওয়ার সম্ভাবনা তৈরি করেছেন। এবং এটি চারপাশে একটি খারাপ জিনিস।

আরও কিছু (আমার কাছে) সুস্পষ্ট প্রশ্নের উত্তর দিতে:

  1. আপনি সি স্টাইল অ্যারে সি ++ এর সাথে মিশ্রণ করছেন। আমি কোনও সি ++ গুরু নই, তবে আমি জানি যে সি ++ এর অ্যারে পরিচালনা করার আরও ভাল (নিরাপদ) উপায় রয়েছে

  2. যদি ক্লাসে ইতিমধ্যে সদস্য ভেরিয়েবল থাকে তবে এগুলি পাস করার দরকার কেন? এটি আর্কিটেকচারাল প্রশ্ন বেশি।

আরও সি ​​++ অভিজ্ঞতা সম্পন্ন অন্যান্য ব্যক্তিদের (10 বা 15 বছর আগে আমি এটি ব্যবহার বন্ধ করে দিয়েছি) সমস্যাগুলি ব্যাখ্যা করার আরও বুদ্ধিমান উপায় থাকতে পারে এবং সম্ভবত আরও সমস্যাগুলি নিয়ে আসবে।


প্রকৃতপক্ষে, vector<int>আরও উপযুক্ত হবে; দৈর্ঘ্য তখন অকেজো হবে। বিকল্পভাবে const int len, যেহেতু পরিবর্তনশীল দৈর্ঘ্যের অ্যারেটি সি ++ স্ট্যান্ডার্ডের অংশ নয় (যদিও কিছু সংকলক এটি সমর্থন করে, কারণ এটি সিটিতে একটি anচ্ছিক বৈশিষ্ট্য)।
ক্রিস্টোফ

5
@ ক্রিস্টোফ লেখক স্থির আকারের অ্যারে ব্যবহার করছিলেন std::array, এটি পরামিতিগুলিতে পাস করার সময় ক্ষয় হয় না এমনটি প্রতিস্থাপন করা উচিত , এর আকার পাওয়ার জন্য আরও সুবিধাজনক উপায় রয়েছে, অনুলিপিযোগ্য এবং overচ্ছিক সীমানা পরীক্ষা করে অ্যাক্সেস করতে পারেন, যখন কোনও ওভারহেড ছাড়েনি সি স্টাইল অ্যারে।
কিউবিক

1
@ কিউবিক: যখনই আমি কোডটি নির্বিচারে স্থির আকারের সাথে অ্যারে ঘোষণা করতে দেখি (যেমন ১০০), আমি নিশ্চিতভাবেই নিশ্চিত যে লেখক এমন একজন শিক্ষানবিস, যিনি এই আজেবাজে এর প্রভাব সম্পর্কে কোনও ধারণা রাখেন না এবং তাকে সুপারিশ করা ভাল ধারণা is এই নকশাকে কোনও পরিবর্তনশীল আকার সহ কিছুতে পরিবর্তন করা হচ্ছে।
ডক ব্রাউন

অ্যারে ঠিক আছে।
মনিকার সাথে হালকাতা রেস

... যারা আমার অর্থ বোঝেন নি তাদের জন্য, জিরো ওয়ান ইনফিনিটি বিধিটিও দেখুন
ডক ব্রাউন

48

কিছু শ্রেণীর ভেরিয়েবলের সাথে শ্রেণিক পদ্ধতিতে কল করা খারাপ নয়। তবে শ্রেণীর বাইরে থেকে এটি করা খুব খারাপ ধারণা এবং আপনার ওও ডিজাইনের একটি মৌলিক ত্রুটি, যা সঠিক এনক্যাপসুলেশনের অনুপস্থিতির পরামর্শ দেয় :

  • আপনার ক্লাসটি ব্যবহার করে যে lenকোনও কোডই জানতে হবে এটি অ্যারের দৈর্ঘ্য এবং ধারাবাহিকভাবে এটি ব্যবহার করুন। এটি ন্যূনতম জ্ঞানের নীতির বিরুদ্ধে যায় । শ্রেণীর অভ্যন্তরীণ বিবরণগুলির উপর যেমন নির্ভরতা অত্যন্ত ত্রুটি-ঝুঁকিপূর্ণ এবং ঝুঁকিপূর্ণ।
  • এটি শ্রেণীর বিবর্তনকে খুব কঠিন করে তুলবে (উদাহরণস্বরূপ যদি একদিন আপনি লিগ্যাসি অ্যারেগুলি পরিবর্তন করতে এবং lenআরও আধুনিকতে চান std::vector<int>), যেহেতু আপনার ক্লাসটি ব্যবহার করে আপনাকে সমস্ত কোডও পরিবর্তন করতে হবে।
  • কোডের যে কোনও অংশই MyClassবিধিমালার (তথাকথিত শ্রেণীর আক্রমণকারী ) সম্মান না করেই কিছু পাবলিক ভেরিয়েবলকে কলুষিত করে আপনার অবজেক্টগুলিতে সর্বনাশ ডেকে আনতে পারে code
  • পরিশেষে, পদ্ধতিটি বাস্তবে শ্রেণীর চেয়ে স্বতন্ত্র, যেহেতু এটি কেবলমাত্র পরামিতিগুলির সাথে কাজ করে এবং অন্য কোনও শ্রেণীর উপাদানের উপর নির্ভর করে না। এই ধরণের পদ্ধতিটি খুব ভালভাবে শ্রেণীর বাইরে একটি স্বাধীন ফাংশন হতে পারে। বা কমপক্ষে একটি স্থিতিশীল পদ্ধতি।

আপনার কোডটি রিফ্যাক্টর করা উচিত এবং:

  • আপনার শ্রেণীর ভেরিয়েবলগুলি তৈরি করুন privateবা protectedনা করুন যদি না এটি না করার উপযুক্ত কারণ থাকে।
  • ক্লাসে করা কর্ম হিসাবে আপনার সর্বজনীন পদ্ধতিগুলি ডিজাইন করুন (যেমন object.action(additional parameters for the action):)।
  • যদি এই রিফ্যাক্টরিংয়ের পরে, আপনার এখনও ক্লাসের ভেরিয়েবলগুলির সাথে কল করার দরকার আছে এমন কিছু ক্লাস পদ্ধতি রয়েছে, তারা জনসাধারণের পদ্ধতিগুলিকে সমর্থনকারী ইউটিলিটি ফাংশন যাচাই করার পরে তাদের সুরক্ষিত বা ব্যক্তিগত করে তুলুন।

7

যখন এই ডিজাইনের উদ্দেশ্যটি আপনি যখন এই শ্রেণীর উদাহরণ থেকে আসে না এমন ডেটার জন্য এই পদ্ধতিটি পুনরায় ব্যবহার করতে সক্ষম হতে চান, তবে আপনি এটি একটি staticপদ্ধতি হিসাবে ঘোষণা করতে চাইতে পারেন ।

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

তবে অন্যান্য উত্তরগুলির দ্বারা উল্লিখিত সুরক্ষা সমস্যাগুলি বৈধ: আপনি উভয় অ্যারে কমপক্ষে lenদীর্ঘ কিনা তা পরীক্ষা করছেন না । আপনি যদি আধুনিক এবং শক্তিশালী সি ++ লিখতে চান তবে আপনার অ্যারে ব্যবহার করা এড়ানো উচিত। std::vectorপরিবর্তে যখনই সম্ভব ক্লাসটি ব্যবহার করুন । নিয়মিত অ্যারেগুলির বিপরীতে, ভেক্টররা তাদের নিজস্ব আকার জানেন। সুতরাং আপনাকে তাদের আকারের নিজের উপর নজর রাখার দরকার নেই। তাদের বেশিরভাগ পদ্ধতিই (সমস্ত নয়!) স্বয়ংক্রিয় বাউন্ড চেকিংও করে, যা আপনাকে গতিরোধ করে যে আপনি শেষটি পড়তে বা লেখার সময় কোনও ব্যতিক্রম পেয়েছেন। নিয়মিত অ্যারে অ্যাক্সেস বাউন্ড চেকিং করে না, যার ফলশ্রুতি সেরা সেগফল্ট হয় এবং এটি আরও খারাপভাবে শোষণমূলক বাফার ওভারফ্লো দুর্বলতার কারণ হতে পারে ।


1

শ্রেণীর একটি পদ্ধতি আদর্শভাবে শ্রেণীর অভ্যন্তরে এনক্যাপসুলেটেড ডেটা ম্যানিপুলেট করে। আপনার উদাহরণে অ্যাড পদ্ধতির কোনও পরামিতি থাকার কোনও কারণ নেই, কেবল শ্রেণীর বৈশিষ্ট্যগুলি ব্যবহার করুন।


0

সদস্য-ফাংশনে কোনও বস্তুর পাসিং (অংশ) ঠিক আছে। যখন আপনার ফাংশন বাস্তবায়ন, আপনি সবসময় আছে সম্ভাব্য এলিয়াসিং সচেতন হতে এবং তার পরিণতি।

অবশ্যই, চুক্তিটি ভাষাটিকে সমর্থন করে এমনকি কিছু প্রকারের এলিয়জিং অপরিজ্ঞাত রেখে দিতে পারে।

বিশিষ্ট উদাহরণ:

  • স্ব-নিয়োগ। এটি একটি হওয়া উচিত, সম্ভবত ব্যয়বহুল, কোনও বিকল্প নেই। এটির জন্য সাধারণ ক্ষেত্রে হতাশ করবেন না।
    অন্যদিকে স্ব-মুভ-অ্যাসাইনমেন্ট, এটি আপনার মুখে বিস্ফোরিত হওয়া উচিত নয়, কোনও অপ-বিকল্প হওয়ার দরকার নেই।
  • ধারকটিতে একটি উপাদানটির একটি অনুলিপি containerোকানো। কিছু একটা v.push_back(v[2]);
  • std::copy() ধরে নেওয়া যায় গন্তব্য উত্সের ভিতরে শুরু হয় না।

তবে আপনার উদাহরণটিতে বিভিন্ন সমস্যা রয়েছে:

  • সদস্য-ক্রিয়াটি এর কোনও প্রিভিলিজেস ব্যবহার করে না, বোঝায় না this। এটি একটি বিনামূল্যে ইউটিলিটি-ফাংশনের মতো কাজ করে যা কেবল ভুল জায়গায়।
  • আপনার শ্রেণি কোনও প্রকার বিমূর্ততা উপস্থাপন করার চেষ্টা করে না । যে সঙ্গে সঙ্গতিপূর্ণ, এটা চেষ্টা করে না encapsulate তার নাড়িভুঁড়ি, কিংবা কোনো বজায় রাখা invariants । এটি নির্বিচার উপাদানগুলির একটি বোবা ব্যাগ।

সংক্ষেপে: হ্যাঁ, এই উদাহরণটি খারাপ। তবে নয় কারণ সদস্য-কার্যটি সদস্য-অবজেক্টগুলি পাস হয়।


0

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

  • শ্রেণি ভেরিয়েবল (প্রকৃত ভেরিয়েবল, ধ্রুবক নয়) হওয়া এড়ানো সম্ভব এবং যদি সম্ভব হয় তবে তা এড়াতে হবে এবং আপনার একেবারেই এটি প্রয়োজন কিনা তা নিয়ে গুরুতর প্রতিফলন ঘটানো উচিত।
  • এই শ্রেণীর ভেরিয়েবলগুলিতে লেখার অ্যাক্সেসটি সম্পূর্ণভাবে সবার জন্য উন্মুক্ত রেখে দেওয়া সর্বজনীনভাবে খারাপ।
  • আপনার ক্লাস পদ্ধতিটি আপনার শ্রেণীর সাথে সম্পর্কিত নয় up এটি আসলে কী এটি একটি ফাংশন যা একটি অ্যারের মানকে অন্য অ্যারের মানগুলিতে যুক্ত করে। এই জাতীয় ফাংশন কোনও ভাষায় ফাংশন হওয়া উচিত যার ফাংশন রয়েছে এবং ভাষাগুলির কোনও ফাংশন নেই এমন ভাষায় "জাল শ্রেণি" (অর্থাত্ কোনও ডেটা বা অবজেক্ট আচরণের সাথে ফাংশনগুলির সংগ্রহ) হওয়া উচিত।
  • বিকল্পভাবে, এই প্যারামিটারগুলি সরান এবং এটিকে একটি সত্য শ্রেণীর পদ্ধতিতে রূপান্তর করুন, তবে এটি পূর্বে উল্লিখিত কারণে খারাপ হবে be
  • আইটি অ্যারে কেন? vector<int>আপনার জীবনকে সহজ করে তুলবে
  • এই উদাহরণটি যদি সত্যিই আপনার ডিজাইনের প্রতিনিধি হয় তবে আপনার ডেটাগুলি বস্তুগুলিতে রাখুন এবং ক্লাসে নয় এবং এই বিষয়গুলির জন্য কনস্ট্রাক্টরগুলি এমনভাবে প্রয়োগ করুন যাতে তৈরির পরে অবজেক্টের ডেটার মান পরিবর্তন করার প্রয়োজন হয় না।

0

এটি C ++ এ যাওয়ার একটি ক্লাসিক "ক্লাস সহ সি" approach বাস্তবে, কোনও পাকা সি ++ প্রোগ্রামার এটি লিখবে না। একটির জন্য, কাঁচা সি অ্যারেগুলি ব্যবহার করা সর্বজনীনভাবে নিরুৎসাহিত, যদি না আপনি একটি ধারক লাইব্রেরি প্রয়োগ করেন।

এর মতো কিছু আরও উপযুক্ত হবে:

// Don't forget to compile with -std=c++17
#include <iostream>
using std::cout; // This style is less common, but I prefer it
using std::endl; // I'm sure it'll incite some strongly opinionated comments

#include <array>
using std::array;

#include <algorithm>

#include <vector>
using std::vector;


class MyClass {
public: // Begin lazy for brevity; don't do this
    std::array<int, 5> arr1 = {1, 2, 3, 4, 5};
    std::array<int, 5> arr2 = {10, 10, 10, 10, 10};
};

void elementwise_add_assign(
    std::array<int, 5>& lhs,
    const std::array<int, 5>& rhs
) {
    std::transform(
        lhs.begin(), lhs.end(), rhs.begin(),
        lhs.begin(),
        [](auto& l, const auto& r) -> int {
            return l + r;
        });
}

int main() {
    MyClass foo{};

    elementwise_add_assign(foo.arr1, foo.arr2);

    for(auto const& value: foo.arr1) {
        cout << value << endl; // arr1 values have been added to
    }

    for(auto const& value: foo.arr2) {
        cout << value << endl; // arr2 values remain unaltered
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.