ভেক্টর 3 ভেক্টর 2 এর উত্তরাধিকারী হওয়া উচিত?


18

আমি শ্রেণীর একটি দম্পতি তৈরি করছি Vector2(এক্স & ওয়াই) এবং Vector3(x, y & টু Z), কিন্তু আমি কিনা জানি না Vector3থেকে উত্তরাধিকারী Vector2, বা পুনরায় বাস্তবায়ন সদস্য ভেরিয়েবল করা হবে কিনা তা m_xএবং m_yআবার? প্রতিটি পক্ষের উপকারিতা এবং বিধিগুলি কী (উত্তরাধিকার বনাম পুনরায় সংজ্ঞা)।

সম্পাদনা করুন: আমি সি ++ (ভিএস 2010) ব্যবহার করছি।


1
এন মাত্রিক ভেক্টরগুলির জন্য কেন একটি সাধারণ ভেক্টর শ্রেণি লিখবেন না এবং তারপরে (যদি প্রয়োজন হয়) একটি ভেক্টর 2 এবং একটি ভেক্টর 3 শ্রেণীর উত্তরাধিকারী হয়। আপনি সাধারণ শ্রেণীর জন্য টেম্পলেটগুলিও ব্যবহার করতে পারেন এবং পূর্ণসংখ্যার ভেক্টর এবং ভাসমান ভেক্টরগুলির জন্য সংস্করণও পেতে পারেন। সম্পাদনা: আপনি কেন একটি অনুকূলিত গণিতের লাইব্রেরি ব্যবহার করবেন না?
দানিজার

5
কল্পনা "Vector3 একটি Vector2 হল" কোন প্রসারিত, তারা পারে একটি পিতা বা মাতা VectorN থেকে উভয় উত্তরাধিকারী যদিও
Wim

1
হ্যাঁ, তবে তার পরে আপনার সম্ভবত ভার্চুয়াল টেবিলের প্রয়োজন হবে এবং এটি রান-টাইম এবং মেমোরির ব্যয়ের ক্ষেত্রে গুরুত্বপূর্ণ। আদর্শভাবে, মেমরিটির সাথে সম্পর্কিত হিসাবে একটি Vector3কেবল 3 হওয়া উচিত floats। এটি অসম্ভব বলে না, কেবল এটি আমি কখনও প্রযোজনা ইঞ্জিনে দেখিনি।
লরেন্ট কুইভিডু

2
হ্যাঁ, আমিও তাই মনে করি। যতক্ষণ না আপনার আর কিছু দরকার নেই floats। আপনি জানেন, YAGNI, KISS, all সমস্ত জিনিস। Vector2, Vector3এবং Vector4কোনও উত্তরাধিকার ছাড়াই এবং floatsগেম ইঞ্জিনগুলির মধ্যে কেবলমাত্র সত্যিকারের স্ট্যান্ডার্ড।
লরেন্ট কুইভিডু

1
আমি আশা করি আপনি বোঝাতে চেয়েছিলেন typedef float real;;)।
ইঙ্গ্রামকে

উত্তর:


47

না এটা করা উচিত নয়। উত্তরাধিকার থেকে আপনি যে জিনিসটি ব্যবহার করবেন তা হ'ল উপাদান xএবং yউপাদান। Vector2ক্লাসে ব্যবহৃত পদ্ধতিগুলি কোনও শ্রেণিতে কার্যকর হবে না Vector3, তারা সম্ভবত বিভিন্ন যুক্তি গ্রহণ করবে এবং বিভিন্ন সদস্য সদস্যের ভেরিয়েবলের উপর ক্রিয়াকলাপ করবে।


+1, আমার পপআপের দিকে বেশি মনোযোগ দেওয়া উচিত যাতে আমি অতিরিক্ত কাজগুলি লিখি না।
ম্যাটসেম্যান

8
ধ্রুপদী উত্তরাধিকার অতিরিক্ত ব্যবহার । একটি Vector3আইএস-নট-এ Vector2(সুতরাং এটি উত্তরাধিকারী হওয়া উচিত নয়) তবে একটি Appleআইএস-এ Fruit(যাতে এটি উত্তরাধিকারী হতে পারে)। আপনি যদি আপনার মনকে যথেষ্ট মোচড় দেন তবে এতে একটি Vector3HAS-A Vector2রয়েছে, তবে কার্যকারিতা হ্রাস এবং কোডিংয়ের অসুবিধা মানে আপনি Vector3এবং এর জন্য সম্পূর্ণ আলাদা ক্লাস লিখবেন Vector2
বোবোবোবো

তবে আপনি (আমার মতে একটি উচিত) একটি 2-ডি ভেক্টর এবং এটি থেকে 3 ডি ভেক্টর উত্তরাধিকারী করার জন্য একটি এন-ডাইমেনশনাল ভেক্টর শ্রেণি লিখতে পারেন।
দানিজর

8

সি ++ এর সাথে আপনি করতে পারেন এমন একটি কৌতূহলী জিনিস রয়েছে (আপনি কোনও ভাষা নির্দিষ্ট করেননি, এবং এই উত্তরটি বেশিরভাগ কারণেই আমার মনে হয় বিকল্পগুলি দেখতে ভাল লাগছে, যদিও আমি সত্যিই বিশ্বাস করি না যে এটি বেশিরভাগ ক্ষেত্রে কার্যকর)।

টেমপ্লেট ব্যবহার করে আপনি এরকম কিছু করতে পারেন:

template <class T, class S, int U>
class VectorN
{
    protected:
        int _vec[U];
    public:
        S& operator+=(const S c)
        {
            for(int i = 0; i < U; i++)
            {
                _vec[i] += c.at(i);
            }
            return (S&)*this;
        }
        int at(int n) const
        {
            return _vec[n];
        }
};

template <class T>
class Vec2 : public VectorN<T,Vec2<T>,2>
{
    public:
        T& x;
        T& y;
        Vec2(T a, T b) : x(this->_vec[0]), y(this->_vec[1])
        {
            this->_vec[0] = a;
            this->_vec[1] = b;
        }
};

template <class T>
class Vec3 : public VectorN<T,Vec3<T>,3>
{
    public:
        T& x;
        T& y;
        T& z;
        Vec3(T a, T b, T c) : x(this->_vec[0]), y(this->_vec[1]), z(this->_vec[2])
        {
            this->_vec[0] = a;
            this->_vec[1] = b;
            this->_vec[2] = c;
        }
};

এবং এটি এর মতো ব্যবহার করা যেতে পারে:

int main(int argc, char* argv[])
{

    Vec2<int> v1(5,0);
    Vec2<int> v2(10,1);

    std::cout<<((v1+=v2)+=v2).x;
    return 0;
}

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


হ্যাঁ, সমস্ত উদারতা সুন্দর বলে মনে হচ্ছে, কেবলমাত্র বেশিরভাগ সময়ে আপনাকে কেবল 3 ভাসমান পয়েন্ট উপাদানযুক্ত একটি স্ট্যান্ডার্ড 3-ভেক্টর প্রয়োজন হয় - সমস্ত অ্যাঙ্গেল বন্ধনীগুলি Vector3f vআরও খানিকটা ফুলে Vector3<float> v
ফুলে

@ বোবোবো হ্যাঁ, আমি সম্মত। আমার ভেক্টর ক্লাসগুলি সাধারণত ভিস 2 এবং কোনও পিতা বা মাতা ছাড়া ভিস 3 থাকে তবে তবুও সেগুলি টেমপ্লেট তৈরি করে। ভেক্টর 3 <ফ্লোট> লেখালেখি যদি আপনাকে বিরক্ত করে, আপনি সর্বদা এটি টাইপ করতে পারেন
লুক বি।

..আর এখন সি প্রোগ্রামার এর যুক্তি .. "তবে টেমপ্লেট ব্যবহারের জন্য সময় বাড়ানোর কমাইল সম্পর্কে কী ??" এই ক্ষেত্রে এটি কি সত্যিই মূল্যবান?
ববোবোবো

@ ববোবোবো আমার সংকলনের সময়গুলি নিয়ে আমার কখনই কোনও সমস্যা হয়নি: পি, তবে আমি কোনও প্রকল্পে কাজ করি নি যে সময় সংকলন একটি সমস্যা হয়ে দাঁড়াবে। একটি যুক্তি দিতে পারে যে সংকলনের সময়গুলি আপনার পূর্ণসংখ্যার প্রয়োজন হলে ভাসা ব্যবহার না করার ন্যায্যতা দেয়।
লুক বি।

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

7

গতি নির্বিশেষে, কোনও উত্তরাধিকার করার সময় আপনার নিজের জিজ্ঞাসা করা উচিত প্রথম প্রশ্নটি যদি আপনি তাদের বহিরাগতভাবে ব্যবহার করছেন। আরও সুনির্দিষ্টভাবে বলতে Vector3গেলে , এমন কোনও পরিস্থিতি রয়েছে যেখানে আপনি নিজেকে এমন একটি ব্যবহার করে দেখতে পাচ্ছেন যে এটি একটি Vector2(যা উত্তরাধিকার সূত্রে আপনি স্পষ্টতই বলছেন যে ভেক্টর 3 "হ'ল" ভেক্টর 2)।

যদি তা না হয় তবে আপনার উত্তরাধিকার ব্যবহার করা উচিত নয়। কোড ভাগ করার জন্য আপনার উত্তরাধিকার ব্যবহার করা উচিত নয়। উপাদান এবং বাহ্যিক ফাংশনগুলির জন্য এটি কি তা নয় যে আপনি যে কোনওভাবে তাদের মধ্যে কোনও কোড ভাগ করে নিচ্ছেন।

হচ্ছে বলেছিলেন যে, আপনি সহজ উপায় চাইতে পারেন ধর্মান্তরিত Vector3 করার গুলি Vector2s, এবং সে ক্ষেত্রে আপনি একটি অপারেটর জমিদার যে পরোক্ষভাবে অগ্রভাগ ছাঁটিয়া হবে লিখতে পারেন Vector3একটি থেকে Vector2। তবে আপনার উত্তরাধিকারী হওয়া উচিত নয়।


ধন্যবাদ, আমি মনে করি যে এটি সমস্যার আলোকপাত করেছে, আমি এটি একটি "কোড ভাগ করে নেওয়ার" দৃষ্টিকোণ থেকে দেখছিলাম (অর্থাত এক্স এবং ওয়াইয়ের মানগুলি "পুনরায় টাইপ না করে")।
ইঙ্গ্রামকে

+1 দুর্দান্ত উত্তর, বিভিন্ন আকারের ভেক্টরগুলির মধ্যে পলিমারফিক ব্যবহার নেই।
লুক বি।

এটি আমার নিজের উত্তরের সাথে যুক্ত হওয়া সবচেয়ে বড় জিনিস - নিশ্চিতভাবে +1। (যদিও অদ্ভুত পরিস্থিতি রয়েছে যেখানে আমি বহুবর্ষের কথা চিন্তা করতে পারি - উদাহরণস্বরূপ, 2.5 ডি 'হাইটম্যাপ' গেমস যেখানে দূরত্বের চেক, পাথিং ইত্যাদির মতো জিনিসগুলি 2 ডি তে করতে চাইবে তবে আপনাকে এখনও অবজেক্টগুলির জন্য 3 ডি স্থানাঙ্ক সরবরাহ করতে হবে)
স্টিভেন স্টাডনিকি 21

@LukeB। Ops ক্ষেত্রে যদিও আমি সম্মত মনে হচ্ছে যে সেখান থেকে উত্তরাধিকারী কোনো কারণ নেই Vector2কিন্তু একটি বেস থেকে inheriting Vector<N>? এটা নিখুঁত জ্ঞান করে তোলে। তদুপরি, উত্তরাধিকারের অর্থ স্বয়ংক্রিয়ভাবে বহুতল আচরণ কেন বোঝায়? সি ++ সম্পর্কে সর্বোত্তম জিনিসগুলির মধ্যে একটি হল আপনার শূন্য দামের উত্তরাধিকার থাকতে পারে। বেস শ্রেণিতে কোনও ভার্চুয়াল পদ্ধতি (ভার্চুয়াল ডেস্ট্রাক্টর সহ) যুক্ত করার দরকার নেই Vector<N>
সমুরসা

5

না, যেহেতু প্রতিটি পদ্ধতির পাশাপাশি ওভাররাইড করা প্রয়োজন তবে এ থেকে উত্তরাধিকার সূত্রে আপনার কোনও ব্যবহার হবে না।

যদি কিছু হয় তবে তারা উভয়ই একটি ভেক্টর ইন্টারফেস প্রয়োগ করতে পারে। তবে, যেহেতু আপনি সম্ভবত কোনও ভেক্টর 2 এবং ভেক্টর 3 এর মধ্যে সাব / ডট / ডিএসটি যুক্ত করতে চান না এটির অবাঞ্ছিত পার্শ্ব প্রতিক্রিয়া হবে। এবং বিভিন্ন পরামিতি থাকা ইত্যাদি ঝামেলা হবে।
সুতরাং আমি সত্যিই এই ক্ষেত্রে উত্তরাধিকার / ইন্টারফেসের কোনও উপকার দেখতে পাচ্ছি না।

উদাহরণ হ'ল লিবিগডিএক্স কাঠামো, যেখানে ভেক্টর 2 এবং ভেক্টর 3 এর একে অপরের সাথে কিছুই করার নেই, একই ধরণের পদ্ধতি ছাড়াও।


2

আপনি যদি সিমডি অ্যারে ব্যবহার করার পরিকল্পনা করেন তবে সম্ভবত এটি সেরা। আপনি যদি এখনও অপারেটর ওভারলোডিং ব্যবহার করতে চান তবে অন্তর্নিহিত অ্যারে অ্যাক্সেস করার জন্য আপনি একটি ইন্টারফেস / মিক্সিন ব্যবহারের বিষয়টি বিবেচনা করতে পারেন - উদাহরণস্বরূপ, এখানে একটি সূচনা পয়েন্ট যা কেবলমাত্র (অপরিবর্তিত) রয়েছে Add

আমি কীভাবে X/ Y/ সরবরাহ করিনি তা লক্ষ্য করুন Z, প্রতিটি VectorXশ্রেণি সরাসরি এটির থেকে উত্তরাধিকারী হবে - অন্যান্য ব্যক্তিদের দ্বারা উল্লিখিত একই কারণে। তবুও, আমি বন্য অঞ্চলে বহুবার ভেক্টর হিসাবে ব্যবহৃত অ্যারেগুলি দেখেছি।

#include <xmmintrin.h>

class Vector
{
public:
    Vector(void)
    {
        Values = AllocArray();
    }

    virtual ~Vector(void) 
    { 
        _aligned_free(Values);
    }

    // Gets a pointer to the array that contains the vector.
    float* GetVector()
    {
        return Values;
    }

    // Gets the number of dimensions contained by the vector.
    virtual char GetDimensions() = 0;

    // An example of how the Vector2 Add would look.
    Vector2 operator+ (const Vector2& other)
    {
        return Vector2(Add(other.Values));
    }

protected:
    Vector(float* values)
    {
        // Assume it was created correctly.
        Values = values;
    }

    // The array of values in the vector.
    float* Values;

    // Adds another vector to this one (this + other)
    float* Add(float* other)
    {
        float* r = AllocArray();

#if SSE
        __m128 pv1 = _mm_load_ps(Values);
        __m128 pv2 = _mm_load_ps(other);
        __m128 pvr = _mm_load_ps(r);

        pvr = _mm_add_ps(pv1, pv2);
        _mm_store_ps(r, pvr);

#else
        char dims = GetDimensions();
        for(char i = 0; i < dims; i++)
            r[i] = Values[i] + other[i];
#endif

        return r;
    }

private:

    float* AllocArray()
    {
        // SSE float arrays need to be 16-byte aligned.
        return (float*) _aligned_malloc(GetDimensions() * sizeof(float), 16);
    }
};

দাবি অস্বীকার: আমার সি ++ স্তন্যপান হতে পারে, আমি এটি ব্যবহার করার পরে অনেক দিন হয়েছে।


অপেক্ষা করুন লোক , আপনার ব্যবহারের _aligned_mallocঅর্থ কি আমি খোলার ত্রুটিটি আসলেই কোনও বাগ নয়?
বোবোবোবো

আপনার মানগুলিকে __m128রেজিস্টার করার জন্য আপনাকে পয়েন্টার কাস্ট ব্যবহার করা উচিত নয় , _mm_loadu_psপরিবর্তে আপনার ব্যবহার করা উচিত । একটি ভাল নমুনা শ্রেণি এখানে "vectorclass.zip" এর অধীনে রয়েছে
বোবোবো

@ বোবোবো আমি একটি সম্পাদনায় সেরা চেষ্টা করব - অস্বীকৃতিটির প্রতি বিশেষ মনোযোগ দিন;)।
জোনাথন ডিকিনসন

@ বোবোবো আপনার সেই কাঠামোটি নিয়ে _mm_loadu_psকাজ করবেন (যেখানে _mm_load_psহবে না)। আমি আপনার পরামর্শটিও যুক্ত করেছি - আপনি যদি মনে করেন যে আমি ভুল গাছটি ছাঁটাই করছি (আমি সি [++] ব্যবহার করে কিছুক্ষণ হয়ে গেছে) প্রশ্নটি সম্পাদন করতে দ্বিধা বোধ করুন।
জোনাথন ডিকিনসন

1

ভেক 2 থেকে ভিসি3 উত্তরাধিকারী হওয়া বা তর্কযোগ্যভাবে উভয়কেই একক ভেক্টর শ্রেণীর উত্তরাধিকারী হওয়াতে আরও একটি গুরুতর কন: আপনার কোড অনেক কিছু করবেভেক্টরগুলিতে অপারেশনগুলি প্রায়শই সময়-সংকটজনক পরিস্থিতিতে থাকে এবং এই সমস্ত অপারেশন যত দ্রুত সম্ভব তা নিশ্চিত করা আপনার সর্বোত্তম আগ্রহের মধ্যে রয়েছে - এটি অন্য অনেকগুলি অবজেক্টের চেয়ে অনেক বেশি বেশ তাই সর্বজনীন বা নিম্ন স্তরের। কোনও উত্তম সংকলক যেকোন উত্তরাধিকারকে ওভারহেড চ্যাপ্টা করার জন্য সর্বোত্তম চেষ্টা করবে, আপনি এখনও তার তুলনায় সেখানে সংকলকটির উপর বেশি নির্ভর করছেন; পরিবর্তে, আমি তাদের যথাসম্ভব অল্প ওভারহেড দিয়ে স্ট্রাক্ট হিসাবে তৈরি করব এবং সম্ভবত তাদের ব্যবহার করা বেশিরভাগ কার্যকারিতা চেষ্টা করব (অপারেটরের মতো জিনিসগুলি বাদ দিয়ে + যা সত্যিকারভাবে সহায়তা করা যায় না) উপরের পদ্ধতিগুলির পরিবর্তে গ্লোবাল হতে হবে struct। প্রাথমিকভাবে অপ্টিমাইজেশনের বিরুদ্ধে সাধারণত সুপারিশ করা হয়, এবং দুর্দান্ত কারণ সহ,


1
-1 কারণ: শ্রেণি এবং কাঠামোর কেবল সি ++ তে অ্যাক্সেস গ্রান্টের অন্তর্ভুক্তি রয়েছে এবং ওপি কোনওভাবেই কোনও ভাষা নির্দিষ্ট করে না, নন-ভার্চুয়াল সদস্য ফাংশনগুলিতে একই সদস্যতার অবিচ্ছিন্ন কার্যকারিতা এবং ভার্চুয়াল সদস্য ফাংশনগুলির (যেমন সম্ভাব্যভাবে প্রদর্শন করে) আপনি যে বিষয়গুলির বিষয়ে উদ্বিগ্ন হন তা কেবলমাত্র বিদ্যমান থাকে যদি আপনি এগুলি তৈরি করেন, কেবল উত্তরাধিকারকে কাজে লাগিয়ে নয়।

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