سؤال

أنا بحاجة إلى استدعاء const وظيفة من غير const الكائن.انظر المثال

struct IProcess {
   virtual bool doSomeWork() const = 0L;
};
class Foo : public IProcess {    
  virtual bool doSomeWork() const {
    ...
  }
};

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {
    getProcess().doSomeWork();        
  }
};

الدعوة

getProcess().doSomeWork();

دائما النتائج في دعوة إلى

IProcess& getProcess()

هل هناك طريقة أخرى للاتصال

const IProcess& getProcess() const 

من غير ثابتة الأعضاء ؟ أنا حتى الآن تستخدم

const_cast<const Bar*>(this)->getProcess().doSomeWork();

الذي لا حيلة ولكن يبدو معقدة للغاية.


تحرير:أود أن أذكر أن قانون يجري بتعميل الترميز في نهاية المطاف وظيفة واحدة فقط لا تزال قائمة.

const IProcess& getProcess() const 

ولكن حاليا هناك تأثير جانبي و const الدعوة قد يعود مختلفة مثيل IProcess بعض الوقت.

يرجى أن نضع في هذا الموضوع.

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

المحلول

وتجنب المدلى بها: تعيين هذا إلى const Bar * أو أيا كان، واستخدام ذلك لاستدعاء getProcess()

وهناك بعض الأسباب متحذلق للقيام بذلك، ولكنه أيضا يجعل من أكثر وضوحا ما تقومون به دون فرض المترجم أن تفعل شيئا قد تكون غير آمنة. منحت، قد لا تصل تلك الحالات، ولكن ربما كنت كذلك أكتب شيئا أن لا يستخدم الزهر في هذه القضية.

نصائح أخرى

const_cast هو الصب بعيدا constness!

أنت الصب من غير const إلى const التي هي آمنة ، وذلك باستخدام static_cast:

   static_cast<const Bar*>(this)->getProcess().doSomeWork();

أعني techincally يتحدث يمكنك أن يلقي في constness مع const_cast, لكنه ليس عملي استخدام المشغل.الغرض من نمط جديد يلقي (مقابل القديم ج-أسلوب فريق العمل) ، يتم التواصل القصد من الزهر. const_cast هو رمز رائحة, و استخدامه ينبغي مراجعتها على الأقل. static_cast من ناحية أخرى آمنة.بل انها مسألة من C++ النمط.

أو يمكنك إنشاء مجموعة جديدة (القطاع الخاص) const الأسلوب ، وندعو أن من doOtherWork:

  void doSomeWorkOnProcess() const { getProcess().doSomeWork(); }

استخدام const المؤقتة هو أيضا خيار (الجواب من "MSN"):

   const Bar* _this = this;
   _this->getProcess().doSomeWork();

إذا getProcess() وgetProcess() const لا تعود إشارة إلى نفس الكائن (ولكن مؤهل بشكل مختلف) ثم فإنه يدل على سوء التصميم من class Bar. الحمولة الزائدة على constness وظيفة ليست وسيلة جيدة للتمييز بين وظائف مع سلوكيات مختلفة.

إذا كانوا يعودون إشارة إلى نفس الكائن ثم:

const_cast<const Bar*>(this)->getProcess().doSomeWork();

و

getProcess().doSomeWork();

والدعوة بالضبط نفس الوظيفة doSomeWork() لذلك ليس هناك حاجة لاستخدام const_cast.

إذا يلقي هو قبيح جدا بالنسبة لك، وبدلا من ذلك يمكن إضافة وسيلة لBar أن مجرد بإرجاع مرجع CONST إلى *this:

Bar const& as_const() const {
    return *this;    // Compiler adds "const" without needing static_cast<>
}

ويمكنك الاتصال ثم <م> أي طريقة const في Bar فقط عن طريق معلق مسبقا as_const().، منها مثلا:

as_const().getProcess().doSomeWork();

وليس لديك للقيام بأي الخداع الصب إذا لم يتم طاقتها وظيفة. استدعاء أسلوب CONST من كائن غير CONST على ما يرام. انها استدعاء أسلوب غير CONST من كائن CONST هذا هو ممنوع. إذا تم تجاوز الأساليب مع CONST وظيفة غير CONST، ثم صب الكائن إلى CONST سوف تفعل خدعة:

const_cast<const IProcess&> (getProcess()).doSomeWork();

وتحرير: أنا لم أقرأ المسألة برمتها. نعم، تحتاج إلى const_cast و<م> هذه المؤشر أو جعل <م> doOtherWork وظيفة CONST للاتصال <م> CONST IProcess وgetProcess () CONST .

وتبقى النقطة التي لا تحتاج كائن CONST للاتصال <م> doSomeWork . ومنذ ذلك هو الهدف، هل تحتاج إلى طريقة CONST يسمى؟

وثمة خيار آخر يتمثل في إعادة تسمية وظائف أكثر من التي تعاني. هذا من شأنه أن يكون فكرة جيدة إذا كانت وظيفة لهما في الواقع مختلفة السلوك / آثار جانبية. وإلا، فإن تأثير استدعاء دالة لا يكون واضحا.

وتحديد قالب

template< class T >
const T & addConst ( T & t ) 
{
    return t;
}

وودعوة

addConst( getProcess() ).doSomeWork();

حسنا، يمكنك أن يعلن

void doOtherWork const ()

وهذا من شأنه أن تفعل ذلك.

وأعتقد أن طريقة const_cast هو الخيار الأفضل لك. هذا هو مجرد وجود قيود على إطار CONST في C ++. أعتقد أن الطريقة الوحيدة التي يمكن أن تجنب صب هي تحديد الطريقة التي يعود CONST IProcess المثال بغض النظر. على سبيل المثال.

const IProcess* getProcessConst() const { return ... }
...
getProcessConst().doSomeWork();

وأفترض أنك تريد DoOtherWork للاتصال واحد من اثنين المكالمات getprocess الخاصة بك اعتمادا على على ما إذا كان يسمى من كائن CONST أم لا.

وأفضل ما يمكن أن تشير إلى هذا:

class Bar
{
public:
   const IProcess& getProcess() const {return ...;}
   IProcess& getProcess() {return ...;}

   void doOtherWork {            // should use getProcess()      
    getProcess().doSomeWork();        
  }
   void doOtherWork const {
    getProcess().doSomeWork();   // should use getProcess() const     
  }
};

وحتى اذا كان يعمل، وهذا يبدو وكأنه رائحة سيئة بالنسبة لي. سأكون حذرا جدا من سلوك الطبقة تغيير جذري وفقا لconstness كائن.

<اقتباس فقرة>   

والسؤال monjardin
   وثمة خيار آخر يتمثل في إعادة تسمية وظائف أكثر من التي تعاني. هذا من شأنه أن يكون فكرة جيدة إذا كانت وظيفة لهما في الواقع مختلفة السلوك / آثار جانبية. وإلا، فإن تأثير استدعاء دالة لا يكون واضحا.

ويتم الوصول IProcess وفي تعليمات برمجية أخرى معظمها من خلال خاصية

__declspec(property(get=getProcess)) IProcess& Process;

وحتى إعادة تسمية وليس خيارا. معظم الوقت <م> CONST نيس وظيفة الدعوة مباريات getProcess () لذلك لم يكن هناك مشكلة.

وأنت في الأساس عالقة مع إعادة تسمية طريقة أو const_cast الآخرين.

وراجع للشغل، وهذا هو واحد من الأسباب التي نسخ على إرسال مؤشرات الذكية لا تعمل في الواقع كذلك في C ++. نسخة على اساس الكتابة مؤشر الذكية هي تلك التي يمكن أن تكون مشتركة ما لا نهاية. عندما يصل المستخدم البيانات في سياق غير CONST، يتم إجراء نسخة من البيانات (إذا كان المستخدم لا تمسك مرجع فريد). هذا النوع من مؤشر يمكن أن تكون مريحة جدا للاستخدام عند مشاركة هياكل البيانات الكبيرة التي تحتاج فقط بعض العملاء لتعديل. معظم التنفيذ "المنطقي" هو أن يكون هناك CONST وغير CONST-operator->. النسخة CONST يعود مجرد المرجعية الأساسية. الإصدار غير CONST يفعل الاختيار مرجعي فريد والنسخ. فشلت في أن تكون مفيدة لمؤشر الذكية غير CONST سيتم استخدام غير CONST-operator-> افتراضيا، حتى إذا كنت تريد استخدام الإصدار CONST. شرط const_cast يجعل من ذاته المستخدم غير ودي.

وأنا الترحيب أي شخص يثبت لي خطأ ويظهر سهل الاستعمال النسخ عند الكتابة المؤشر في C ++ ...

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