سؤال

أنا أعمل على فئتين مجمّعتين تحددان أنواع البيانات الحقيقية والمعقدة.تحدد كل فئة منشئات مثقلة، بالإضافة إلى العوامل الحسابية الأربعة +،-،*،/ وخمسة عوامل إسناد =،+= وما إلى ذلك.لتجنب تكرار التعليمات البرمجية، كنت أفكر في استخدام وظائف القالب عندما تكون وسيطات الجانب الأيسر والأيمن للمشغل من نوع بيانات مختلف:

// real.h
class Real {
public:
  explicit Real(const double& argument) {...}
  explicit Real(int argument) {...}
  ...

  friend const operator*(const Real&; const Real&);
  template <class T> friend const Real operator*(const Real&, const T&);
  template <class T> friend const Real operator*(const T&, cont Real&);
  // Here, T is meant to be a template parameter for double and int

  // Repeat for all other arithmetic and assignment operators
};

// complex.h
class Complex {
public:
  explicit Complex(const Real& realPart) {...}
  explicit Complex(const Real& realPart, const Real& imaginaryPart) {...}
  // Overload for double and int data types
  ...

  friend const operator*(const Complex&, const Complex&);
  template <class T> friend const Complex operator*(const Complex&, const T&);
  template <class T> friend const Complex operator*(const T&, cont Complex&);
  // Here, T is is a template parameter for Real, double and int

  ...
};

المشكلة هنا هي أن الكود مثل:

//main.cpp
void main() {
  Complex ac(2.0, 3.0);
  Real br(2.0);
  Complex cc = ac * br;
}

إرجاع المترجم (مجلس التعاون الخليجي) خطأ التحميل الزائد الغامض لـ "المشغل *" في "ac * br", ، لأن المترجم لا يستطيع التمييز بين:

  • template <class T> friend const Complex operator*(const Complex&, const T&) [مع T = حقيقي]
  • template <class T> friend const Real operator*(const T&, cont Real&) [مع T = مركب]

هل هناك طريقة لتحديد أن T لا يمكن أن يكون مركبًا في تعريف عامل تشغيل القالب* في الفئة Real؟أو هل يجب علي الاستغناء عن القوالب وتحديد كل عامل لكل مجموعة محتملة من أنواع بيانات الوسيطات؟أم أن هناك طريقة لإعادة تصميم الكود؟

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

المحلول

اه مشكلة المشغلين..

أنشأ Boost مكتبة رائعة، بحيث أنه من خلال توفير الحد الأدنى من المنطق، تتم إضافة كافة الأشكال الأخرى تلقائيًا لك!

نلقي نظرة على Boost.Operators !

الآن بالنسبة لمشكلتك، كما لاحظت، سيتعين عليك تحديد كلا نوعي العوامل (int وdouble) بدلاً من استخدام قالب عام.إذا كان هناك الكثير من المنطق في عوامل التشغيل هذه (وهو ما أشك فيه)، فيمكنك دائمًا مطالبتهم باستدعاء طريقة شائعة (مقولبة).

template <typename T>
Complex complex_mult_impl(T const& lhs, Complex const& rhs) { ... } // Note (1)

// return type is not 'Complex const', see (2)
Complex operator*(int lhs, Complex const& rhs)
{ 
  return complex_mult_impl(lhs,rhs);
}

ولكن إذا كنت تستخدم Boost.operators فإنك توفر فقط Complex::operator*=(int) وComplex::operator*=(double) وسيتم استنتاج الإصدارات المستقلة تلقائيًا :)

(1) يمكنك استخدام قيمة التمرير هنا، إذا كانت جميع الوسائط مدمجة.قد ترغب أيضًا في التفكير Boost.CallTraits, ، والذي يختار تلقائيًا بين القيمة الثانوية والمرجع حسب ما إذا كانت الوسيطة مضمنة أم لا.إنه مفيد للقوالب.

(2) عند إرجاع الحجج حسب القيمة، فمن غير المنطقي تصنيفها على أنها const.ال const الكلمة الرئيسية تعني فقط شيئًا للمراجع والمؤشرات، هنا لا شيء يمنع المستخدم من إنشاء نسخة "بسيطة" Complex...وأنت محظوظ لأنه لا!

نصائح أخرى

يمكنك جعل الفئة الحقيقية أو المعقدة تحتوي على عوامل ضرب غير عامة.

class Real 
{
  ........

  template <class T> const Real operator*(const T&);
  const Real operator*(const Real&);

};

هل يمكنك توضيح المنشئات المعقدة؟وهذا يعني أن التحويل الضمني من حقيقي إلى معقد غير مسموح به ويجب توضيح عامل التشغيل *

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