كيفية التعامل مع المصفوفات (المعلنة على المكدس) في C++?

StackOverflow https://stackoverflow.com/questions/55093

  •  09-06-2019
  •  | 
  •  

سؤال

لدي الدرجة تحليل مصفوفة أن يحافظ على النتيجة في مجموعة الأعضاء:

class Parser
{
  ...
  double matrix_[4][4];
};

المستخدم من هذه الفئة يحتاج إلى استدعاء دالة API (كما في وظيفة لدي أي سيطرة على ، لذلك لا استطيع تغيير واجهة لجعل الأشياء تعمل بسهولة أكثر) التي تبدو مثل هذا:

void api_func(const double matrix[4][4]);

الطريقة الوحيدة التي يمكنني الخروج مع المتصل تمرير صفيف نتيجة الدالة هي جعل الأعضاء العام:

void myfunc()
{
  Parser parser;
  ...
  api_func(parser.matrix_);
}

هل هذه الطريقة الوحيدة لفعل الأشياء ؟ أنا ذهولها كيف مرنة المصفوفات متعددة الأبعاد أعلن من هذا القبيل.اعتقد matrix_ ستكون أساسا نفس double** وأنا يمكن أن يلقي (بأمان) بين البلدين.كما اتضح, لا أستطيع العثور على أحد غير آمنة طريقة يلقي بين الأشياء.أقول إضافة إلى accessor Parser الدرجة:

void* Parser::getMatrix()
{
  return (void*)matrix_;
}

هذا سوف ترجمة, ولكن لا استطيع استخدامه, لأن هناك لا يبدو أن يكون وسيلة إلى الزهر إلى الأطوار نوع مصفوفة:

  // A smorgasbord of syntax errors...
  api_func((double[][])parser.getMatrix());
  api_func((double[4][4])parser.getMatrix());
  api_func((double**)parser.getMatrix()); // cast works but it's to the wrong type

الخطأ هو:

خطأ C2440:'نوع الزهر' :لا يمكن التحويل من 'الفراغ *' إلى 'const مزدوجة [4][4]'

...مع فضول الإضافة:

لا توجد تحويلات إلى مجموعة أنواع ، على الرغم من أن هناك التحويلات إلى إشارات أو مؤشرات إلى المصفوفات

لا أستطيع تحديد كيفية يلقي إلى مرجع أو مؤشر إلى الصفيف أيضا ولو أنه ربما لن مساعدتي هنا.

للتأكد من ذلك ، في هذه المرحلة المسألة الأكاديمي البحت ، void* يلقي بالكاد أنظف من فئة واحدة الأعضاء اليسار العامة!

هل كانت مفيدة؟

المحلول

وهنا لطيفة, تنظيف طريقة:

class Parser
{
public:
   typedef double matrix[4][4];

   // ...

   const matrix& getMatrix() const
   {
      return matrix_;
   }

   // ...

private:
  matrix matrix_;
};

الآن أنت تعمل مع وصفي اكتب اسم بدلا من صفيف ، ولكن منذ typedef المترجم لا تزال تسمح بتمريرها إلى ثابت دالة API التي تأخذ نوع قاعدة.

نصائح أخرى

جرب هذا.وهي تجمع نظيفة في دول مجلس التعاون الخليجي 4.1.3:

typedef double FourSquare[4][4];

class Parser
{
  private:
    double matrix_[4][4];

  public:
    Parser()
    {
        for(int i=0; i<4; i++)
          for(int j=0; j<4; j++)
            matrix_[i][j] = i*j;
    }

  public:
    const FourSquare& GetMatrix()
    {
        return matrix_;
    }
};

void api_func( const double matrix[4][4] )
{
}

int main( int argc, char** argv )
{
    Parser parser;
    api_func( parser.GetMatrix() );
    return 0;
}

لقد استعملت الاتحاد مثل هذا لتمرير حول المصفوفات في الماضي:

union matrix {
    double dflat[16];
    double dmatr[4][4];
};

ثم تمرير مؤشر إلى اضع ونسخ البيانات إلى المصفوفة في صفك.

هناك طرق التعامل مع هذا وإلا (التي هي أكثر عمومية) ، ولكن هذا الحل يميل إلى أن يكون أنظف في النهاية في تجربتي.

ظننت matrix_ أساسا نفس مزدوجة**

في ج هناك صحيح المصفوفات متعددة الأبعاد ، وليس صفائف من المؤشرات والمصفوفات ، لذلك مزدوجة[4][4] هو متجاورة مجموعة من أربعة مزدوجة[4] المصفوفات ، أي ما يعادل ضعف[16] ، وليس (ضعف*)[4].

لا توجد تحويلات إلى مجموعة أنواع ، على الرغم من أن هناك التحويلات إلى إشارات أو مؤشرات إلى المصفوفات صب قيمة مزدوجة[4][4] أن محاولة لبناء واحدة على المكدس - أي ما يعادل std::string(محلل.getMatrix()) - إلا أن مجموعة لا إمدادات مناسبة منشئ.ربما كنت لا تريد أن تفعل ذلك ، حتى إذا كنت يمكن.

منذ النوع بترميز خطوة, كنت في حاجة الى نوع كامل (مزدوجة[][] لن تفعل).يمكنك تفسير يلقي الفراغ* إلى ((مزدوجة[4][4])*), ثم تأخذ المرجعية.لكن من الأسهل أن الرموز المميزة ل typedef المصفوفة والعودة إشارة من النوع الصحيح في المقام الأول:

typedef double matrix_t[4][4];

class Parser
{
    double matrix_[4][4];
public:
    void* get_matrix () { return static_cast<void*>(matrix_); }

    const matrix_t& get_matrix_ref () const { return matrix_; }
};

int main ()
{
    Parser p;

    matrix_t& data1 = *reinterpret_cast<matrix_t*>(p.get_matrix());

    const matrix_t& data2 = p.get_matrix_ref();
}

وضع على اختيار الإجابة مراقبة هذا الخط

const matrix& getMatrix() const

هذا شيء عظيم, كنت لا داعي للقلق حول مؤشرات الصب.أنت تعود المرجعية الأساسية مصفوفة الكائن.IMHO المراجع هي واحدة من أفضل الميزات من C++, الذي افتقد عندما الترميز في مباشرة C.

إذا كنت لم تكن مألوفة مع الفرق بين المراجع مؤشرات في C++ ، قراءة هذا

على أية حال, عليك أن تكون على علم أنه إذا كان Parser الكائن الذي يملك الأساسية مصفوفة كائن يخرج من نطاق أي قانون الذي يحاول الوصول إلى مصفوفة عبر هذه الإشارة الآن سيتم الرجوع خارج نطاق الكائن سوف تحطم الطائرة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top