Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

1

28.08.2016, 15:34

[C++] C225 "Item": Instanz von abstrakter Klasse kann nicht erstellt werden

Hallo,

das Problem, um was es geht, steht im Titel. Ich habe eine Basisklasse (Item). Von dieser Erben alle Items, zb. der "Enlarger" (macht die Spielfigur größer). Der Itemmanager verwaltet alle Items und entscheidet je nach erzieltem Combo, welches Item erstellt werden soll.
Erstmal etwas Code:

Item.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#ifndef ITME_H
#define ITEM_H

#include <SFML\Graphics.hpp>

class Item : public sf::Drawable, public sf::Transformable
{
public:
    Item();

    virtual void update(float frametime) = 0;

    void setSpeed(float speed);

    float getSpeed() const;

private:
    virtual void draw(sf::RenderTarget &target, sf::RenderStates states) const = 0;

    float _speed = 45.f;
};

#endif // !ITME_H


Enlarger.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef ENLARGER_H
#define ENLARGER_H

#include <game\items\Item.h>
#include <core\Resource.h>
#include <SFML\Graphics.hpp>

class Enlarger : public Item
{
public:
    Enlarger();

    void update(float frametime) override;

private:
    void draw(sf::RenderTarget &target, sf::RenderStates states) const override;

private:
    sf::Sprite _sprite;
};

#endif // !ENLARGER_H


Enlarger.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <game\items\Enlarger.h>

///////////////////////////////////////////////////////////////////////////////////////////////
Enlarger::Enlarger()
{
    // initialize the sprite
    _sprite.setTexture(Resource::getTexture("enlarger.png"));
    _sprite.scale(sf::Vector2f(0.05f, 0.05f));
}
///////////////////////////////////////////////////////////////////////////////////////////////
void Enlarger::update(float frametime)
{
    // move the sprite
    _sprite.move(sf::Vector2f(0.f, this->getSpeed() * frametime));
}
///////////////////////////////////////////////////////////////////////////////////////////////
void Enlarger::draw(sf::RenderTarget& target, sf::RenderStates states) const
{
    // present the sprite on the screen
    target.draw(_sprite);
}


Itemmanager.h:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#ifndef ITEMMANAGER_H
#define ITEMMANAGER_H

#include <SFML\Graphics.hpp>
#include <game\items\Enlarger.h>

#include <vector>

class Itemmanager : public sf::Drawable
{
public:
    Itemmanager();

    void update(float frametime, sf::RenderWindow& rw);
    void addItem(int combo, sf::Vector2f position);

private:
    void draw(sf::RenderTarget &target, sf::RenderStates states) const override;

private:
    std::vector<Item> _items;
};

#endif // !ITEMMANAGER_H


Itemmanager.cpp:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <game\items\ItemManager.h>

///////////////////////////////////////////////////////////////////////////////////////////////
Itemmanager::Itemmanager()
{
}
///////////////////////////////////////////////////////////////////////////////////////////////
void Itemmanager::update(float frametime, sf::RenderWindow& rw)
{
    // call the update method for each item
    for (int it = 0; it < _items.size(); it++)
    {
        _items.at(it).update(frametime);

        // if the item has left the window, then delete it
        if (_items.at(it).getPosition().y > rw.getSize().y)
        {
            //_items.erase(_items.begin() + it);
        }
    }
}
///////////////////////////////////////////////////////////////////////////////////////////////
void Itemmanager::addItem(int combo, sf::Vector2f position)
{
    bool spawn_probability = std::rand() % 2;

    // if the spawn_probability equals 1, then check with item so spawn
    if (spawn_probability == true)
    {
        // if the combo is equals 2, then spawn an enlarger
        if (combo == 2)
        {
            Enlarger enlarger;
            enlarger.setPosition(position);
            _items.push_back(enlarger);
        }
    }
}
///////////////////////////////////////////////////////////////////////////////////////////////
void Itemmanager::draw(sf::RenderTarget & target, sf::RenderStates states) const
{
    // draw the itmes
    for (int it = 0; it < _items.size(); it++)
    {
        target.draw(_items.at(it));
    }
}


Der Fehler: C2259 "Item": Instanz von abstrakter Klasse kann nicht erstellt werden.

Wo steckt der Fehler?

Vielen Dank im Voraus :D

MitgliedXYZ

Alter Hase

Beiträge: 1 369

Wohnort: Bayern

  • Private Nachricht senden

2

28.08.2016, 15:47

Wikipedia Zitat

Zitat

Eine abstrakte Klasse bezeichnet in der objektorientierten Programmierung eine spezielle Klasse, welche sich per Definition nicht instanziieren lässt (d.h. es lassen sich keine Objekte von ihr erzeugen) und die somit lediglich als Strukturelement innerhalb einer Klassenhierarchie dient. Innerhalb von abstrakten Klassen besteht die Möglichkeit abstrakte Methoden (also Methoden ohne „Rumpf“ (Implementierung) nur mit der Signatur) zu deklarieren.

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

3

28.08.2016, 15:52

Wikipedia Zitat

Zitat

Eine abstrakte Klasse bezeichnet in der objektorientierten Programmierung eine spezielle Klasse, welche sich per Definition nicht instanziieren lässt (d.h. es lassen sich keine Objekte von ihr erzeugen) und die somit lediglich als Strukturelement innerhalb einer Klassenhierarchie dient. Innerhalb von abstrakten Klassen besteht die Möglichkeit abstrakte Methoden (also Methoden ohne „Rumpf“ (Implementierung) nur mit der Signatur) zu deklarieren.

Ich weiß, dass ich von einer abstrakten Klasse keine Instanz erstellen kann. Ich erstelle lediglich eine Instanz von der Klasse Enlarger, welche nicht abstrakt ist. Deshalb habe ich die Frage gestellt, warum dieser Fehler erscheint

4

28.08.2016, 15:58

Wenn du dir bei VC den Fehler neben dem Fehlerfenster auch im 'Ausgabe'-Fenster anschaust, wird dir meist mehr Fehlerinformation angegeben. So auch, welche Methode nicht überschrieben wurde.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

5

28.08.2016, 16:15

Dein Problem ist der vector<Item>. Du brauchst einen vector<Item*> oder besser noch mit Smart-Pointern vector<unique_ptr<Item>>.

TGGC

1x Rätselkönig

Beiträge: 1 799

Beruf: Software Entwickler

  • Private Nachricht senden

6

28.08.2016, 16:33

Du solltest entweder noch ein paar Grundlagen lernen oder deine Systeme weniger kompliziert designen. Du hattest ja jetzt schon 2 Probleme kurz hintereinander...

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

7

28.08.2016, 17:27

Dein Problem ist der vector<Item>. Du brauchst einen vector<Item*> oder besser noch mit Smart-Pointern vector<unique_ptr<Item>>.

Tut mir leid, aber es funktioniert immer noch nicht :(
ich habe ihn so deklariert: std::vector<std::unique_ptr<Item>> _items;
und versuche so die Elemente hinzuzufügen:
//std::unique_ptr<Enlarger> enlarger;
Enlarger enlarger;
//enlarger->setPosition(position);
enlarger.setPosition(position);
_items.push_back(enlarger);


Fehler: "[...]Keine Instanz von Überladene Funktion[...]". Habe ich etwas falsch verstanden?

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

8

28.08.2016, 17:30

Du kannst unique_ptr nicht einfach so pushen, weil dabei eine Kopie erzeugt würde (da war übrigens auch vorher schon dein Problem, denn aus einem Enlarger wurde ein Item erstellt, bzw. wurde eben nicht, weil Item ja abstrakt ist) und das widerspricht unique. Du kannst aber natürlich auch nicht einfach eine Enlarger-Instanz in einen Vector pushen, der unique_ptrs erwartet.
Da kommt das Stichwort std::move in's Spiel. Das sind allerdings wichtige Konzept im Umgang mit Smart-Pointern, ohne deren Details du da hängen bleibst. In diesem Zusammenhang sind übrigens auch Kopier-Konstruktoren und Move-Konstruktoren ganz wichtig, ohne die das ganze Konzept von unique und move total unverständlich ist.
Polymorphie solltest du dir ebenfalls noch einmal anschauen, denn die wichtigste Voraussetzung für Polymorphie hast du offenbar noch nicht verinnerlicht: Polymorphie funktioniert nur auf Pointer/Referenz-Typen.
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

9

28.08.2016, 18:18

Das mit std::move ist allerdings für einen Einsteiger schwierig zu verstehen. Es ist vollkommen in Ordnung, wenn du da erst einmal hängen bleibst. Nun kannst du entweder den "einfachen" Weg gehen und normale Zeiger benutzen statt Smart-Pointer (früher oder später wirst du merken, dass sie sinnvoll sind) oder aber du nimmst dir vor, es von Beginn an richtig zu lernen. Das ist dir überlassen.

cojo2015

Alter Hase

  • »cojo2015« ist der Autor dieses Themas

Beiträge: 516

Wohnort: bei mir zu Hause

Beruf: Schüler

  • Private Nachricht senden

10

28.08.2016, 18:34

Das mit std::move ist allerdings für einen Einsteiger schwierig zu verstehen. Es ist vollkommen in Ordnung, wenn du da erst einmal hängen bleibst. Nun kannst du entweder den "einfachen" Weg gehen und normale Zeiger benutzen statt Smart-Pointer (früher oder später wirst du merken, dass sie sinnvoll sind) oder aber du nimmst dir vor, es von Beginn an richtig zu lernen. Das ist dir überlassen.

Wird dann eine Kopie des Objektes bei dem std::move erstellt?

Werbeanzeige