لماذا يفشل التحويل بين المشتق* إلى قاعدة* بميراث خاص؟

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

سؤال

ها هو الكود الخاص بي -

#include<iostream>
using namespace std;

class base
{
public:
    void sid()
    {
    }  
};

class derived : private base
{
public:
    void sid()
    {
    }
};

int main()
{
    base * ptr;
    ptr = new derived; // error: 'base' is an inaccessible base of 'derived'
    ptr->sid();
    return 0;
}

هذا يعطي خطأ في وقت الترجمة.

error: 'base' is an inaccessible base of 'derived'

لأن المترجم سيحاول الاتصال بالفئة الأساسية sid() لماذا أحصل على هذا الخطأ؟ هل من أحد يفسر لي هذا.

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

المحلول

$ 11.2/4 حالات-

يمكن الوصول إلى الفئة B الأساسية من N في R ، إذا

  • سيكون العضو العام الذي تم اختراعه في B عضوًا عامًا في N ، أو
  • يحدث R في أحد أعضاء أو صديق للفئة N ، وسيكون عضوًا عامًا تم اختراعه في B عضوًا خاصًا أو محميًا في N ، أو
  • يحدث R في عضو أو صديق للفئة P المستمدة من N ، وسيكون عضوًا عامًا تم اختراعه في B عضوًا خاصًا أو محميًا في P ، أو
  • يوجد فئة S بحيث تكون B فئة أساسية يمكن الوصول إليها في R و S فئة أساسية من N يمكن الوصول إليها في R. "

هنا "B" هو "قاعدة" ، "n" "مشتقة" و "r" هو الرئيسي.

  1. النظر في الرصاصة الثانية- "R تحدث في عضو أو صديق لفئة N ، ...". لا ينطبق هذا البند على أنه "R" (الرئيسي) ليس عضوًا أو صديقًا لـ 'n' (مشتق)

  2. النظر في الرصاصة الثالثة- "R تحدث في عضو أو صديق للفئة P ....". لا ينطبق هذا claus أيضًا على نفس الأسباب الواردة أعلاه

  3. النظر في الرصاصة الرابعة- مرة أخرى هذا البند لا ينطبق

وبالتالي يمكننا أن نستنتج أن "القاعدة" ليست فئة يمكن الوصول إليها من "مشتقة".

$ 11.2/5 حالات -

إذا كانت الفئة الأساسية متاحة ، فيمكن للمرء تحويل مؤشر ضمنيًا إلى فئة مشتقة إلى مؤشر إلى تلك الفئة الأساسية (4.10 ، 4.11). [ملاحظة: يترتب على ذلك أن الأعضاء وأصدقاء الفئة X يمكنهم تحويل X* ضمنيًا إلى مؤشر إلى فئة قاعدة خاصة أو محمية من X. - تنفيذ

حيث Base ليست فئة يمكن الوصول إليها Derived عند الوصول إليها main, ، التحويل القياسي من الفئة المشتقة إلى الفئة الأساسية غير متشابه. وبالتالي الخطأ.

تحرير 2:

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

المراجع هي من مشروع قياسي N3000. أنا بعد أن قمت بتنزيل أحدث مسودة :)

GCC prog.cpp: في الدالة "int main ()": prog.cpp: 27: خطأ: "القاعدة" هي قاعدة لا يمكن الوصول إليها من "المشتقة"

Comeau Online "ComeAustest.c" ، السطر 26: خطأ: التحويل إلى فئة قاعدة لا يمكن الوصول إليها غير مسموح بها "قاعدة" ptr = جديدة ؛

VS2010 خطأ C2243: "اكتب المصبوب": التحويل من "مشتق *" إلى "قاعدة *" ، ولكن لا يمكن الوصول إليه

نصائح أخرى

أظن أن المشكلة هي أنه لا يمكنك تحويل مؤشر مشتق إلى مؤشر أساسي ، لأن الميراث خاص.

قدم Chusbad شرحًا متعمقًا يتضمن المعيار ، سأحاول تقديم تفسير يمكن الوصول إليه.

في C ++ ، هناك 3 محددات مستوى الوصول: public, protected و private. تهدف هذه إلى تحديد من يمكنه الوصول إلى أساليب أو سمات أو فئات أساسية. إنه نموذجي بين اللغات الموجهة نحو الكائن.

هنا ، انتخبت private ميراث. من الناحية المفاهيمية ، هذا يعني أنك تسعى إلى إخفاء حقيقة ذلك Derived يرث من Base إلى الغرباء ، مما يعني عمومًا أن هذه تفاصيل تنفيذ.

نتيجة لذلك ، فإن "الخارج" غير مدرك لهذه العلاقة. يتم فرض هذا من قبل المترجم مع هذا inaccessible رسالة.

من وجهة نظر التصميم ، private الميراث غير مطلوب بشكل عام. إما أن ينطبق مبدأ استبدال Liskov وتستخدمه public الميراث ، إما أنها تفاصيل التنفيذ وتستخدم التكوين.

هل تعلم أن class derived يرث من class base, ، لكن ال main() الوظيفة لا تعرف ذلك. السبب main() الوظيفة لا تعرف أنها صنعت class derived يرث من القطاع الخاص من class base.

لذلك عندما تحاول التعيين new derived إلى ptr, ، أنواع المؤشرات غير متوافقة.

جرب هذا:

#include<iostream>
#include<conio.h>
using namespace std;

class base
{
      private:
      public:
          virtual void sid() // You might want to declare sid virtual
             {
                  cout<<"base";
             } 
          virtual ~base() // You then probably need a virtual destructor as well.
             {
             } 
};

class derived : public base //public inheritance
{
      private:
      public:
             void sid()
             {
                  cout<<"derived";
             }
};

int main()
{
    base * ptr;
    ptr = new derived;
    ptr->sid();
    getch();
    return 0;
}

هذا يعطي خطأ C2243: "النوع المصبوب": موجود من "مشتق *" إلى "قاعدة *" ، ولكن لا يمكن الوصول إليه ، وقد تم توريث هذا الفئة المشتقة بشكل خاص. لذا ، لا يتم إنشاء كائن الفئة الأساسي عند حدوث إنشاء الحصول على الحصول على الحصول على. لإنشاء مكالمات كائن Derive ، يذهب أولا لإنشاء كائن الفئة الأساسي الذي لا يحدث. Soltuion هو اشتقاق الفصل علنا. لا يهم ما إذا كنت تستخدم الكلمة الرئيسية الافتراضية مع وظائف الأعضاء أم لا.

تحتاج إلى إعلان وظيفة SID () في الفئة الأساسية على أنها افتراضية. يمكن استبدال وظيفة افتراضية بفئة مشتقة. خلاف ذلك ، من المحتمل أن تحصل على خطأ في المترجم.

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