2017-06-23 1 views
-1

Ich denke, dass Java möglich ist, das Objekt der Kindklasse durch das Objekt der Elternklasse zu ersetzen. Ich möchte es in C++ machen.Wie das Objekt der untergeordneten Klasse zurückgegeben wird, wenn der Funktionsrückgabetyp die übergeordnete Klasse ist?

Ich versuche es wie folgt zu tun. Allerdings habe ich "Fehler: Rückgabetyp 'Essen' ist eine abstrakte Klasse" Fehler. Wie kann ich es reparieren?

Vor es funktioniert:

#include <iostream> 

using namespace std; 

class Food { 
    public: 
     virtual void SetPrice(int myprice) = 0; 
     int GetPrice() { 
      return price; 
     } 
    protected: 
     int price; 
}; 

class Fruit : public Food { 
    public: 
     void SetPrice(int myprice) { 
      price = myprice - 20; 
     } 
}; 

class Fish : public Food { 
    public: 
     void SetPrice(int myprice) { 
      price = myprice/2; 
     } 
}; 

int main(int argc, char* argv[]) 
{ 
    Food *pFood; 
    Fruit myFruit; 
    Fish myFish; 

    if (strcmp(argv[1], "fruit") == 0) { 
     pFood = &myFruit; 
    } else { 
     pFood = &myFish; 
    } 

    pFood->SetPrice(100); 
    cout << pFood->GetPrice() << endl; 

    return 0; 
} 

Nach Klassendefinition weggelassen. es nicht funktioniert:

Food getFoodObject(string type) 
{ 
    if (strcmp(type, "fruit") == 0) { 
     Fruit myFruit; 
     return &myFruit; // I don't want to write 2 lines. I want to return the above line. This is my another question... 
    } 

    Fish myFish; 
    return &myFish; 
} 

int main(int argc, char* argv[]) 
{ 
    Food *pFood; 

    pFood = getFoodObject(argv[1]) 

    pFood->SetPrice(100); 
    cout << pFood->GetPrice() << endl; 

    return 0; 
} 

Update 1

Dank vieler Ratschläge, war mein Problem gelöst. Ich muss C++ 11 verwenden, also verwende ich unique_ptr statt make_unique.

std::unique_ptr<Food> getFoodObject(string type) 
{ 
    if (type == "fruit") { 
     return std::unique_ptr<Fruit>(new Fruit); 
    } 
    return std::unique_ptr<Fish>(new Fish); 
} 

int main(int argc, char* argv[]) 
{ 
    std::unique_ptr<Food> pFood = getFoodObject(argv[1]); 

    pFood->SetPrice(100); 
    cout << pFood->GetPrice() << endl; 

    return 0; 
} 

@dlasalle über Boost-Bibliothek erwähnt. Ich werde ein Update veröffentlichen, nachdem ich Boosts intelligenten Zeiger als meine Notiz verwenden kann.

+0

Also haben Sie 2 Fragen oder eine? : P – gsamaras

+0

'pFood' ist ein Zeiger. 'getFoodObject' gibt ein Objekt und keinen Zeiger zurück. In Java sind fast alles implizite Zeiger. Also sollten Sie auch mit Zeigern arbeiten, um das zu erreichen, was Sie wollen – Alexey

+1

Post echten Code! '' strcmp (type, "fruit") '' wird nicht mit '' string type'' kompiliert. –

Antwort

1

Sie müssen nach Zeigertyp oder Verweis auf die Basisklasse zurückgeben, nicht nach Wert. Dies ist erforderlich, da Ihre Basisklasse eine abstrakte Klasse ist und Sie keine abstrakte Klasse instanziieren können. Das heißt Sie nur

tun können
Food* getFoodObject(string type) 
{ 
    if (strcmp(type, "fruit") == 0) { 
     Fruit myFruit; 
     return &myFruit; // I don't want to write 2 lines. I want to return the above line. This is my another question... 
    } 

    Fish myFish; 
    return &myFish; 
} 

Denn dann werden Sie einen Zeiger auf eine Funktion lokales Objekt zurückkehrt, und sobald die Funktion das Objekt verlässt zerstört wird Sie mit einem baumelnden Zeiger zu verlassen. Was können wir tun, ist, den Code ändern ein std::unique_ptr zu verwenden (ein Smart-Pointer verwendet, da es den Speicher für uns verwaltet) und dann könnte man so etwas wie

std::unique_ptr<Food> getFoodObject(string type) 
{ 
    if (type == "fruit") { 
     return std::unique_ptr<Fruit>(new Fruit); 
     // or in C++14 return std::make_unique<Fruit>(); 
    } 
    return std::unique_ptr<Fish>(new Fish); 
    // or in C++14 return std::make_unique<Fish>(); 
} 

haben Und Sie würden die Funktion wie

int main(int argc, char* argv[]) 
{ 
    std::unique_ptr<Food> pFood = getFoodObject(argv[1]) 

    pFood->SetPrice(100); 
    cout << pFood->GetPrice() << endl; 

    return 0; 
} 
nennen

Beachten Sie auch, dass if (strcmp(type, "fruit") == 0) ungültig ist. strcmp befasst sich mit C-Strings, nicht std::string. Um eine std::string zu vergleichen, können Sie einfach == wie if (type == "fruit")

+0

Sie vermissen ein paar 'Rückkehr's dort. – themiurge

+0

@thiemurge Danke. überschrieb sie bei Unfall – NathanOliver

+0

Es erfordert C++ 14) Offensichtlich versteht er nicht, wie Speicher in C++ funktioniert, wie er Zeiger auf Stack zugeordneten Objekten zurückgibt. – Alexey

1

verwenden Sie können einen Zeiger in C++ verwenden. Eine abstrakte Klasse kann nicht instanziiert werden, daher können Sie die abstrakte Basisklasse nicht als Instanz verwenden. Sie können die übergeordnete konkrete Klasse erstellen und dann einen Zeiger auf die Basisklasse festlegen.

2

In Java geben Sie immer eine Referenz (einen verherrlichten Zeiger) zurück, aber in C++ haben Sie die Möglichkeit, das Objekt nach Wert, Verweis oder Zeiger zurückzugeben. Polymorphie in C++ ist nur über Referenzen und Zeiger zulässig.

Wenn Sie die Elternklasse als Wert zurückgeben, erhalten Sie am Ende object slicing, aber Sie erhalten auch eine Instanz einer abstrakten Klasse, die nicht gültig ist (also der Compilerfehler).

Sie wollen, so etwas tun:

#include <memory> 

std::unique_ptr<Food> getFoodObject(string type) 
{ 
    std::unique_ptr<Food> ptr; 
    if (type.compare("fruit") == 0) { 
     ptr.reset(new Fruit()); 
    } else { 
     ptr.reset(new Fish()); 
    } 

    return ptr; 
} 

Wenn Sie nicht mit C++ 11, müssen Sie entweder boost ‚s intelligente Zeiger oder einfach roh Zeiger verwenden.

+0

Vielen Dank für Ihre Erklärung. Ich werde über Polymorphie in C++ verstehen. – zono

Verwandte Themen