كيف يمكنني الحصول على سلوك متعدد الأشكال في منشئ C ++؟

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

  •  12-09-2019
  •  | 
  •  

سؤال

لدي فئة أساسية أريد أن أبدو مثل هذا:

class B
{
    // should look like: int I() { return someConst; }
    virtual int I() = 0;
    public B() { something(I()); }
}

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

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

هل هناك طريقة للحصول على نفس التأثير؟


مرتكز على هذا الرابط يبدو أن الجواب لا توجد وسيلة للحصول على ما أريد. لكن ما تقوله هو:

الجواب القصير هو لا. لا يعرف الطبقة الأساسية أي شيء عن الفئة التي اشتقتها منها وهي شيء جيد أيضا. [...] وهذا هو، فإن الكائن لا يصبح رسميا مثيلا للمشتقون 1 حتى يبدأ المنشئ 1 :: مشتق 1.

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

(الآن مرة أخرى لقراءة هذا الرابط)

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

المحلول

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

يجب عليك إعادة التفكير في التصميم الخاص بك - تمرير الثابت كوسيطة للمتند، على سبيل المثال.

class B
{
public:
    explicit B(int i)
    {
        something(i);
    }
};

يرى الأسئلة الشائعة C ++ للمزيد من. اذا أنت حقا تريد استدعاء الوظائف الافتراضية أثناء البناء، اقرا هذا.

نصائح أخرى

ربما استخدام طريقة المصنع الثابتة على كل نوع مشتق؟ هذه هي الطريقة المعتادة لبناء كائنات غريبة (اقرأ: أولئك الذين لديهم متطلبات تهيئة محددة للغاية) في .NET، التي أتتكر فيها.

class Base
{
  protected Base(int i)
  {
    // do stuff with i
  }
}

class Derived : public Base
{
  private Derived(int i)
    : Base(i)
  {
  }

  public Derived Create()
  {
    return new Derived(someConstantForThisDerivedType);
  }
}

إن استدعاء الأساليب الافتراضية عبارة عن منشئين في الأساس عبث عموما، لأنك لا يمكن أن تكون متأكدا من سلوك طريقة معينة، و (كما يشير شخصا آخر بالفعل إلى الخارج) لم يتم استدعاء منشئين مشتقين بعد.

لن يعمل هذا كما لا توجد فئة مشتقة بعد عند تنفيذ منشئ الفئة الأساسية:

class Base
{
public:
    Base()
    {
        // Will call Base::I and not Derived::I because
        // Derived does not yet exist.
        something(I());
    }

    virtual ~Base() = 0
    {
    }

    virtual int I() const = 0;
};

class Derived : public Base
{
public:
    Derived()
     : Base()
    {
    }

    virtual ~Derived()
    {
    }

    virtual int I() const
    {
        return 42;
    }
};

بدلا من ذلك، يمكنك إضافة الحجج إلى منشئ الطبقة الأساسية:

class Base
{
public:
    explicit Base(int i)
    {
        something(i);
    }

    virtual ~Base() = 0
    {
    }
};

class Derived : public Base
{
public:
    Derived()
     : Base(42)
    {
    }

    virtual ~Derived()
    {
    }
};

أو إذا كنت مغرم حقا من OOP، فيمكنك أيضا إنشاء فئة إضافية:

class Base
{
public:
    class BaseConstructorArgs
    {
    public:
        virtual ~BaseConstructorArgs() = 0
        {
        }

        virtual int I() const = 0;
    };

    explicit Base(const BaseConstructorArgs& args)
    {
        something(args.I());
    }

    virtual ~Base() = 0
    {
    }
};

class Derived : public Base
{
public:
    class DerivedConstructorArgs : public BaseConstructorArgs
    {
    public:
        virtual ~DerivedConstructorArgs()
        {
        }

        virtual int I() const
        {
            return 42;
        }
    };

    Derived()
     : Base(DerivedConstructorArgs())
    {
    }

    virtual ~Derived()
    {
    }
};

ما تحتاجه هو بناء المرحلة الثانية. وبعد استخدم علاج مبرمج العالمي: إضافة طبقة أخرى من عدم الإنذار.

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