سؤال

هل من الممكن الإعلان عن متغير في لغة c++ دون إنشاء مثيل له؟أريد أن أفعل شيئا مثل هذا:

Animal a;
if( happyDay() ) 
    a( "puppies" ); //constructor call
else
    a( "toads" );

في الأساس، أريد فقط الإعلان عن خارج الشرط حتى يحصل على النطاق الصحيح.

هل هناك أي طريقة للقيام بذلك دون استخدام المؤشرات والتخصيص a على الكومة؟ربما شيء ذكي مع المراجع؟

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

المحلول

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

هل يمكن، مع ذلك، تشغيل منشئ معلمات لتبدأ:

Animal a(getAppropriateString());

وأو هل يمكن فعلا استخدام شيء مثل ?: operator لتحديد سلسلة الصحيح. (تحديث: أعطىGreg بناء الجملة من أجل هذا نرى أن الجواب)

نصائح أخرى

وأنت لا يمكن تعريف متغير دون استدعاء منشئ. ومع ذلك، في المثال الخاص بك يمكنك أن تفعل ما يلي:

Animal a(happyDay() ? "puppies" : "toads");

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

حقا، لديك خياران هنا:

1- اذهب مع المؤشرات:

Animal* a;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );

// ...
delete a;

2- أضف طريقة Init إلى Animal:

class Animal 
{
public:
    Animal(){}
    void Init( const std::string& type )
    {
        m_type = type;
    }
private:
    std:string m_type;
};

Animal a;
if( happyDay() ) 
    a.Init( "puppies" );
else
    a.Init( "toads" );

أنا شخصياً سأختار الخيار 2.

وأنا أفضل إجابة جريج، ولكن هل يمكن أيضا القيام بذلك:

char *AnimalType;
if( happyDay() ) 
    AnimalType = "puppies";
else
    AnimalType = "toads";
Animal a(AnimalType);

وأقترح هذا لأنني عملت الأماكن التي كان ممنوعا المشغل مشروط. (تنهد!) أيضا، وهذا يمكن توسيعها إلى ما بعد بديلين بسهولة جدا.

إذا كنت ترغب في تجنب جمع القمامة - هل يمكن استخدام المؤشر الذكية

auto_ptr<Animal> p_a;
if ( happyDay() )
    p_a.reset(new Animal( "puppies" ) );
else
    p_a.reset(new Animal( "toads" ) );

// do stuff with p_a-> whatever.  When p_a goes out of scope, it's deleted.

إذا كنت لا تزال تريد استخدام. جملة بدلا من ->، يمكنك أن تفعل هذا بعد التعليمة البرمجية أعلاه:

Animal& a = *p_a;

// do stuff with a. whatever

وبالإضافة إلى الإجابة جريج Hewgill، وهناك عدد قليل من الخيارات الأخرى:

وارفع خارج الجسم الرئيسي من التعليمات البرمجية في وظيفة:

void body(Animal & a) {
    ...
}

if( happyDay() ) {
  Animal a("puppies");
  body( a );
} else {
  Animal a("toad");
  body( a );
}

و(أ ب) استخدام وضع الجديد:

struct AnimalDtor {
   void *m_a;
   AnimalDtor(void *a) : m_a(a) {}
   ~AnimalDtor() { static_cast<Animal*>(m_a)->~Animal(); }
};

char animal_buf[sizeof(Animal)]; // still stack allocated

if( happyDay() )
  new (animal_buf) Animal("puppies");
else
  new (animal_buf) Animal("toad");

AnimalDtor dtor(animal_buf); // make sure the dtor still gets called

Animal & a(*static_cast<Animal*>(static_cast<void*>(animal_buf));
... // carry on

وأفضل عمل حول هو استخدام المؤشر.

Animal a*;
if( happyDay() ) 
    a = new Animal( "puppies" ); //constructor call
else
    a = new Animal( "toads" );

نعم، يمكنك القيام بعمل ما يلي:

Animal a;
if( happyDay() )
    a = Animal( "puppies" );
else
    a = Animal( "toads" );

وهذا سوف ندعو المنشئات بشكل صحيح.

وتحرير: نسيت شيئا واحدا ... عندما يعلن ذلك، سيكون لديك لاستدعاء منشئ ذلك، سواء كان منشئ لا يفعل شيئا، أو لا يزال تهيئة القيم أيا كان. ولهذا الأسلوب إنشاء كائنين، واحدة في التهيئة واحدة داخل إذا البيان.

وهناك طريقة أفضل سيكون لخلق وظيفة الحرف الأول () من الدرجة، مثل:

Animal a;
if( happyDay() )
    a.init( "puppies" );
else
    a.init( "toads" );

وبهذه الطريقة سيكون أكثر كفاءة.

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