يمكن إعادة تعريف المعامل [] داخل الفئات لجعلها تعمل مثل المصفوفه احادية البعد، و لكن كيف يمكن اعادة تعريفه ليعمل مثل المصفوفه المتعددة الأبعاد
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 5 أكتوبر 2009 في 06:52
مدونتي: C++ Tips and Tricks
يمكن إعادة تعريف المعامل [] داخل الفئات لجعلها تعمل مثل المصفوفه احادية البعد، و لكن كيف يمكن اعادة تعريفه ليعمل مثل المصفوفه المتعددة الأبعاد
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 5 أكتوبر 2009 في 06:52
مدونتي: C++ Tips and Tricks
السؤال غير واضح ضع مثال الى ما تريد
اقتباسالسؤال غير واضح ضع مثال الى ما تريد
إذا وضعت مثال لما اريد، إذا ما الهدف من السؤال :)
و لكن لتقريب الصوره هذا مثال على اعادة تعريف المعامل []
[color= #0000ff;]template [color= #000000;]<[color= #0000ff;]typename T[color= #000000;]>
[color= #0000ff;]class [color= #0000ff;]Array
[color= #000000;]{
[color= #0000ff;]public[color= #000000;]:
[color= #0000ff;]Array[color= #000000;]([color= #0000ff;]int count[color= #000000;]) [color= #000000;]: size[color= #000000;](count[color= #000000;])
[color= #000000;]{ arr [color= #000000;]= [color= #0000ff;]new T[color= #000000;][count[color= #000000;]]; [color= #000000;]}
T[color= #000000;]& operator[color= #000000;][[color= #000000;]] [color= #000000;]([color= #0000ff;]int i[color= #000000;]) [color= #007f00;]// i is the index
[color= #000000;]{ [color= #0000ff;]return arr[color= #000000;][i[color= #000000;]]; [color= #000000;]}
~[color= #0000ff;]Array[color= #000000;]([color= #000000;])
[color= #000000;]{ [color= #0000ff;]delete[color= #000000;][[color= #000000;]] arr; [color= #000000;]}
[color= #0000ff;]private[color= #000000;]:
T[color= #000000;]* arr;
[color= #0000ff;]int size
[color= #000000;]}السؤال الأن اذا قمت بجعل الفئه Array تمثل مصفوفه متعددة الأبعاد فكيف اقوم بإعادة تعريف المعامل [] ليتم استخدامه مع الفئه Array مثلما نستخدمه مع المصفوفات متعددة الأبعاد الإفتراضيه الخاصه باللغه ؟
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 5 أكتوبر 2009 في 08:41
مدونتي: C++ Tips and Tricks
قم بعمل إعادة تحميل للقوسين () ، [] تأخذ رقم واحد فقط :) .
او اعمل كلاس تاني يرجه اول قيمة في عنصر المصفوفة
template <typename T>class
helper {public: const T operator[](int j) const;
T& operator[](int j);};
template <typename T>
class array
{
public:
const helper operator[](int i) const;
helper& operator[](int i); // returns an object which overloads []
};BEng , Electronics and communications.
Embedded systems engineer.
Graphics Programmer
عالم الكومبيوتر هو من لديه المعرفة في علوم الكومبيوتر ، الرياضيات ، هندسة الالكترونيات -احمد صالح
اقتباسقم بعمل إعادة تحميل للقوسين ()
هل تعطينى مثال على اعادة تعريف القوسين () لمثال الفئه Array بالأعلى ؟
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 5 أكتوبر 2009 في 10:35
مدونتي: C++ Tips and Tricks
السلام عليكم...
أخي محمد, هناك الكثير من الطرق, و لكن بشكل عام سيكون هناك مقايضة بين الأداء و بين عمومية الاستخدام. فمثلاً vector يعيد reference لنفسه, و هكذا.
خذ مثلاً هذا المثال:
struct oneD
{
int elem[3];
int& operator[](size_t index)
{
return elem[index];
}
};
struct twoD
{
oneD elem[3];
oneD& operator[](size_t index)
{
return elem[index];
}
};
int main()
{
twoD matrix;
matrix[0][0] = 0;
int x = matrix[0][0];
}كل مافي الأمر, هو أننا أعدنا مرجعاً لكائن آخر هو الآخر أعاد تعريف المعامل [].
هل عدد الأبعاد التي لديك ثابت أم متغير؟
هل يهمك سهولة كتابة الكود, لأن هناك طريقة أخرى عن طريق بناء proxy, لبناء مصفوفة متغيرة الأبعاد عالية الكفاءة, و لكن الأمر للأسف يحتاج إلى الكثير من الجهد و التجارب في هذه الحالة :)
تحياتي...
اقتباسهل عدد الأبعاد التي لديك ثابت أم متغير؟
عدد الأبعاد متغير
اقتباسهل يهمك سهولة كتابة الكود
لا يهمنى سهولة الكود بقدر ما يهمنى كفاءة الأداء
اقتباسهناك طريقة أخرى عن طريق بناء proxy, لبناء مصفوفة متغيرة الأبعاد عالية الكفاءة
كيف يمكن ان تتم هذه العمليه ؟؟
اقتباسو لكن الأمر للأسف يحتاج إلى الكثير من الجهد و التجارب في هذه الحالة
على استعداد له بإذن الله و لكن اعرف كيف اولا.
و شكرا لك اخى.
و الله ولى التوفيق
مدونتي: C++ Tips and Tricks
أهلاً محمد,
اقتباسعدد الأبعاد متغير
حتى أكون صريحاً معك, الأمر أكبر من مستواي :)
يمكنك ببساطة فعل هذا الشيء بـ vector أو deque مع توفير ما تطلبه من استعمال [] بشكل متغير. و لكن هناك ضريبة في الكفاءة.
تصور مثلاً أن لدينا:
std::vector< std::vector<double> >
كل عنصر في المصوفة الكبيرة عبارة عن مصفوفة, موجودة في مكان مختلف عن المصفوفة التي تليها. بالطبع هذا يعني أنه مهما كان عدد الأبعاد ليس هناك مشكلة, و لكن المشكلة أنه في النهاية عملية الإدخال ستتم عن طريق إنشاء مصفوفة من نوع:
vector<double>
و من ثم يتم إدرجها في المصفوفة الكبيرة. هذا مثلاً لو أن لديك بعدان فقط.
ما تريد فعله موجود بالفعل, لذلك الحياة صعبة بدون boost في c++ :)
The Boost Multidimensional Array Library
لاحظ أن موقع المكتبة عندما يذكر المصفوفات الثابتة, وهو الشيء الذي يريد محاكاة عمله:
double matrix[3][3]
فإن المترجم يقوم بتخزين الـ 9 عناصر في أماكن متجاورة في الذاكرة. و يقوم بتوفير دالة تحويل للأبعاد على الشكل التالي:
matrix[j] == matrix[i*rowsize + j]
هذا بالطبع في اللغة نفسها.
عموماً, أتمنى أن تجد طريقة جيدة لحل الموضوع, و سأحاول أن أضع فكرة الـ proxy التي في رأسي في القريب العاجل :)
تحياتي...
تم تعديل هذه المشاركة بواسطة Khaled.Alshaya في 5 أكتوبر 2009 في 20:47
طيب ليه متتبعش الطريقة الطبيعية فى تعريف المصفوفات متعددة اﻷبعاد؟, و هى إنها مصفوفات ذات بعد واحد بس مكونة من مصفوفات.
Array< Array<int> > r;
و ساعتها ممكن تستخدم [] طبيعى و بأى عمق إنت عايزه على حسب تعريفك.
اقتباسطيب ليه متتبعش الطريقة الطبيعية فى تعريف المصفوفات متعددة اﻷبعاد؟, و هى إنها مصفوفات ذات بعد واحد بس مكونة من مصفوفات.و ساعتها ممكن تستخدم [] طبيعى و بأى عمق إنت عايزه على حسب تعريفك.
فكره جميله ، هجرب و اضيف النتيجه
مدونتي: C++ Tips and Tricks
السلام عليكم ورحمه الله وبركاته ،،
طبعا يمكن في البداية عمل class سواء template أو none-template لكل من واحد من الأبعاد التي تريدها ، مثلا تريد بعدين 2D قم بعمل كلاس يعيد تعريف المعامل ( ) ومرر له البعدين (x,y) ، وهكذا بالنسبة للثلاثه أبعاد أو الأربعه ... طبعا حل غير عملي ويتطلب اعادة كتابة لكل من هذه الأبعاد :) .
الحل الأخر كما وضح أخ Blouteeth وكما قمت به في مثالك هو عمل class يمثل بعد واحد فقط وبعدها يمكنك انشاء عدد الأبعاد التي تريدها من خلال عمل Instantiating الclass من خلال الclass نفسه كأنه نوع بيانات ،، وهذا المثال :
#ifndef __ARRAYS__
#define __ARRAYS__
template <typename T >
class Arrays {
public:
Arrays (int aSize = def ) : size(aSize) {
ptrArray = new T [ size ];
}
const T& operator[] (int index) const {
return ptrArray[index];
}
T& operator [] ( int index ) {
return ptrArray[index];
}
~Arrays () {
delete [] ptrArray;
}
private :
int size;
T* ptrArray;
static const int def = 4;
};
#endif // __ARRAYS__ولتجربته :
// Arrays.cpp
#include <iostream>
using namespace std;
#include "Arrays.h"
int main ( int argc, char* argv[] ) {
Arrays <int> oneDim(3);
Arrays <Arrays<int> > twoDim(3);
Arrays <Arrays<Arrays<int> > > threeDim(3);
oneDim[0] = 10;
twoDim[1][2] = 4;
threeDim[1][2][2] = 3;
cout << oneDim[0] << endl;
cout << twoDim[1][2] << endl;
cout << threeDim[1][2][2] << endl;
return (0);
}والكود سوف يعمل على ما يرام ،، لكن الSyntax شويه متعب وممل لمستخدم الكلاس :) ..
هناك طريقة متقدمة في الtemplate تسمى template recursion ويمكن استخدامها في هذه الحالة (كتابة Real N-Dimensional Arrays) ،، لأن السطر :
Arrays <Arrays<Arrays<int> > > threeDim(3);
يمكن تصوره على أنه recursive فالأبعاد الثلاثه هي في الحقيقة Arrays من بعد واحد من Arrays من بعد واحد من Arrays من النوع int (يعتبر الbase-case) . وبدلا من جعل مستخدم الكلاس يقوم بهذه الخطوه الممله يمكنك توفير template recursion class وسوف يكون الإستخدام بهذا الشكل :
NArrays<int,1> oneDim; NArrays<int,2> twoDim; NArrays<int,3> threeDim;
الكلاس NArrays سوف يستقبل النوع وعدد الأبعاد في ال NArrays ، وبما أن أي عنصر من البعد الثالث سوف يكون هو NArrays من بعدين وأي عنصر في هذين البعدين سوف يكون NArrays من بعد واحد ، اذا سوف يكون لدينا في الكلاس مؤشر الى الكلاس NArrays من النوع المحدد والبعد -1 (3 هو 2 والذي هو 1 وهنا سيتم التوقف ) . أترككم مع المثال فلن تتضح الفكرة الا بالمثال :
template < typename T , int N >
class NArrays {
public :
NArrays () : size(def) {
ptrArray = new NArrays<T,N-1>[size];
}
~NArrays(){
delete [] ptrArray;
}
const NArrays<T,N-1>& operator [] (int index) const {
return ptrArray[index];
}
NArrays<T,N-1>& operator[] (int index) {
return ptrArray[index];
}
private:
int size;
NArrays<T,N-1>* ptrArray;
static const int def = 4;
};وسوف نقوم الأن بكتابة Partial specialization من الكلاس للbase case وهو البعد الأول الذي سيتوقف فيه.
template < typename T >
class NArrays<T,1> {
public :
NArrays (int aSize = def ) {
ptrArray = new T [aSize];
}
~NArrays() {
delete [] ptrArray;
}
const T& operator[] (int index) const {
return ptrArray[index];
}
T& operator [] ( int index ) {
return ptrArray[index];
}
private :
int size;
T* ptrArray;
static const int def = 4;
};ولتجربة المثال :
// NArrays.cpp
#include <iostream>
using namespace std;
#include "NArrays.h"
int main ( int argc, char* argv[] ) {
NArrays<int,1> oneDim;
NArrays<int,2> twoDim;
NArrays<int,3> threeDim;
oneDim[0] = 10;
twoDim[1][2] = 4;
threeDim[1][2][2] = 3;
cout << oneDim[0] << endl;
cout << twoDim[1][2] << endl;
cout << threeDim[1][2][2] << endl;
return (0);
}في المرفق نفس المثال من كتاب Professional C plus plus ويحتوي على زيادة دوال في الكلاس (Assignment , copy constructor وغيرهم ).. قمت بنسخه من الكتاب ووضعه في ملف cpp .
بالتوفيق ،،
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
جزاك الله خيرا اخى وجدى، هذه فعلا ما كنت اريد.
لدى سؤال
فى الكود التالى
NArrays [color= #000000;]([color= #000000;]) [color= #000000;]: size[color= #000000;](def[color= #000000;]) [color= #000000;]{
ptrArray [color= #000000;]= [color= #0000ff;]new NArrays[color= #000000;]<T,N[color= #ff0000;]-1[color= #000000;]>[color= #000000;][size[color= #000000;]];
[color= #000000;]}يتم انشاء الفئه Narray و يتم تمرير عدد الأبعاد فى كل مره بقيمه اصغر من سابقتها فمتى سيتم التوقف عن انشاء نسخ منها.
و ما فائدة النسخه NArrays<T,1> حيث انه لم يتم استخدامها.
و الله ولى التوفيق
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 7 أكتوبر 2009 في 08:22
مدونتي: C++ Tips and Tricks
عندما يصل للبعد 1 ، وسسيتخدم حينها الPartial specialization وهنا الكلاس الجديد سينشئ في تلك اللحظه النوع T .
بالتوفيق ،
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
اقتباسعندما يصل للبعد 1 ، وسسيتخدم حينها الPartial specialization وهنا الكلاس الجديد سينشئ في تلك اللحظه النوع T .
هل هذا يعنى انه اذا كتبت 20 داله داخل الفئه NArrays<T,N-1> لابد و ان اعيد كتابتهم داخل الفئه NArrays<T,1> ؟
مدونتي: C++ Tips and Tricks
هذه هي ضريبة استخدامك للTemplate Recursion :) .. فالPartial specialization يجب أن يستخدم نفس الدوال بالضبط في الكلاس الذي قام بعمل specialization ، ويمكن أن يقوم بتغيير تطبيقها بما يلزم وأحيانأ تكون كما هي بالضبط ،،،
على العموم لا توجد طريقة متكاملة ،، وكلما أردنا التسهيل على مستخدم الكلاس سنجد المهمة أصبحت أكثر صعوبة من ناحية مبرمج الكلاس ، والعكس صحيح أيضا في حال أردنا تصعيب المهمه على مستخدم الكلاس..
بالتوفيق أخي الكريم محمد ،،
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
طب لو قلنا مثلا بدل من اعادة كتابة الفئة بأكملها لتكون ذات بعد واحد و قمت بوراثتها ببعد واحد و اقصد كالتالى
[color= #0000ff;]template [color= #000000;]<[color= #0000ff;]typename T, [color= #0000ff;]int D[color= #000000;]>
[color= #0000ff;]class NArray
[color= #000000;]{
...
...
...
[color= #000000;]};
[color= #0000ff;]template [color= #000000;]<[color= #0000ff;]typename T[color= #000000;]>
[color= #0000ff;]class NArray [color= #000000;]: [color= #0000ff;]public NArray[color= #000000;]<T,[color= #ff0000;]1[color= #000000;]>
[color= #000000;]{
...
...
...
[color= #000000;]};الكود السابق هو نظرى اى لم اطبقه.
هل سيسمح المترجم بهذا؟ و إن سمح هل سيعتبر ان الفئه الأب و الفئه الأخرى هما من نوع واحد ام سيحتاج لإنشاء نسخة ذات بعد واحد خاصه به؟
تم تعديل هذه المشاركة بواسطة Muhammad alaa في 7 أكتوبر 2009 في 08:45
مدونتي: C++ Tips and Tricks
المشكلة سوف تكون أن الكلاس الأب ليس له علاقه بالإبن حينها ،وسوف يحتوي على متغيرات مثل المؤشر NArrays<T,N-1>* ptrArray; والإبن ليس بحاجة له ،،
وعند انشاء الكائن بالبعد 1 قد تحصل مشكلة حيث أن أي انشاء لكائن subclass سوف يتم استدعاء الsuperclass مباشره ، وقد يتسبب هذا في مشكلة infnite recursion .. لم أجرب ولكنها قد تكون كذلك والله اعلم ...
انت خسران ايه يا محمد ، عملية copy & paste وينتهي الموضوع :D
http://informatic-ar.com منصة تعليمية عربية في علوم الحاسب والبرمجة
https://moalfat.com للكتب الالكترونية والكورسات التعليمية
Everything we see now is just an engineering solution based on old science
اقتباسانت خسران ايه يا محمد ، عملية copy & paste وينتهي الموضوع
انا مش خسران حاجه :lol: بس الفكره كلها انى كنت بدور على طريقه حتى لو كان الكود فيها طويل و صعب بس الأداء فيها عالى و ايضا المساحه التى تستهلكها هذه الطريقه اقل ما يمكن طبعا بالإضافه لحجم المصفوفه نفسها.
شكرا اخ وجدى :)
و الله ولى التوفيق
مدونتي: C++ Tips and Tricks
المتواجدون خلال آخر دقيقتين · يتحدّث كل ٣٠ ثانية
جارٍ التحقق من المتواجدين…