الإعلان عن كائن قبل تهيئته في لغة c++
-
03-07-2019 - |
سؤال
هل من الممكن الإعلان عن متغير في لغة 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" );
وبهذه الطريقة سيكون أكثر كفاءة.