Frage

Ist es möglich, eine Variable in C ++ zu erklären, ohne es zu instanziieren? Ich möchte so etwas wie dies tun:

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

Basially, ich will nur eine außerhalb des bedingten erklären, damit es den richtigen Rahmen bekommt.

Gibt es eine Möglichkeit, dies zu tun, ohne Zeiger und Zuordnen a auf dem Heap verwenden? Vielleicht etwas Gescheites mit Referenzen?

War es hilfreich?

Lösung

Sie können dies nicht direkt in C ++, da das Objekt aufgebaut ist, wenn Sie es mit dem Standard-Konstruktor definieren.

Sie könnte jedoch eine parametrisierte Konstruktor laufen zu beginnen:

Animal a(getAppropriateString());

Oder man könnte tatsächlich so etwas wie die ?: operator verwenden, um die richtige Zeichenfolge zu bestimmen. (Update:. @ Greg gab die Syntax für diese diese Antwort sehen)

Andere Tipps

Sie können nicht eine Variable deklarieren, ohne einen Konstruktor aufrufen. in Ihrem Beispiel Sie können jedoch wie folgt vor:

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

Sie können Referenzen hier nicht verwenden, da, sobald Sie aus dem Umfang bekommen würden, würde der Verweis auf ein Objekt zeigen, die gelöscht werden würden.

Wirklich, haben Sie zwei Möglichkeiten hier:

1- mit Zeigern gehen:

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

// ...
delete a;

2 Fügen Sie eine Init-Methode 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" );

ich persönlich mit der Option 2 gehen würde.

Ich ziehe Gregs Antwort, aber man könnte dies auch tun:

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

Ich schlage vor, das, weil ich Orte gearbeitet habe, wo der Bedingungsoperator verboten war. (Seufz!) Dies kann auch über zwei Alternativen erweitert wird sehr leicht.

Wenn Sie die Garbage Collection vermeiden wollen -. Sie einen Smart-Pointer verwenden könnte

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.

Wenn Sie immer noch die verwendet werden sollen. statt Syntax -> können Sie diese nach dem Code tun oben:

Animal& a = *p_a;

// do stuff with a. whatever

Neben Greg Hewgill Antwort, gibt es ein paar andere Optionen:

Nehmen Sie den Hauptteil des Codes in eine Funktion aus:

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

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

(Ab) Verwenden Platzierung neu:

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

Die beste Arbeit um ist Zeiger zu verwenden.

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

Ja, können Sie Folgendes tun:

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

Das wird die Konstrukteure richtig nennen.

EDIT: vergessen eine Sache ... Wenn ein erklären, haben Sie noch einen Konstruktor aufrufen, ob es ein Konstruktor sein, die nichts tut, oder initialisiert noch die Werte zu was auch immer. Dieses Verfahren erzeugt daher zwei Objekte, die bei der Initialisierung und die einer in der if-Anweisung.

Eine bessere Möglichkeit wäre, eine Funktion init () der Klasse zu erstellen, wie zum Beispiel:

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

Auf diese Weise wäre effizienter.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top