Tablica elementów klasy bazowej

0

witam,
Mam abstrakcyjną klasę bazową A oraz kilka klas dziedziczących po niej nazwijmy je B C D E. Chcę jak w javie stworzyć do nich jedną wspólną tablicę do zapisu da się zrobić coś takiego w cpp?

2

Tak.

0

A jak to zrobić ?

0

i jak to ewentualnie zrobić z wykorzystaniem vectora z biblioteki vector?

4
#include <iostream>
#include <memory>
#include <vector>
using namespace std;

struct base {
	virtual void foo() {
		cout << "base" << endl;
	}
};

struct a: base {
	void foo() override {
		cout << "a" << endl;
	}	
};
struct b: base {
	void foo() override {
		cout << "b" << endl;
	}
};

int main() {
	vector<unique_ptr<base>> container;
	
	for(int i = 0; i < 5; ++i) {
		container.emplace_back(new a{});
		container.emplace_back(new b{});
	}
	
	for(auto &el: container) {
		el->foo();
	}
	return 0;
}

http://ideone.com/5RH6ji

0

d406071ee3.png

2

Na przyszłość wstawiaj swój kod w znaczniki i uważniej analizuj kod użytkowników, którzy Ci odpowiadają. Użyj emplace_back.

0

Ok dziękuje za pomoc tylko jest jeden problem mianowicie po dodaniu obiektu metodą emplace_back() wyskakuje mi błąd że podany obiekt nie posiada tej metody. Mam rozumieć że metoda emplace_back tworzy element klasy A za pomocą konstruktora klasy potomnej i obcina go z jego prywatnych pól?

0

Nie mogę usunąć poprzedniego postu
Chodziło mi że po utworzeniu obiektu metodą emplace_back wywołując ten obiekt dostaje komunikat że podany obiekt nie posiada tego pola.

edit wszystko ok zapomniałem że muszę użyć -> zamiast .
post do zamknięcia dzięki za pomoc

0
class Panelclass
{
private:
    vector <unique_ptr<Aclass>> classList;

public:
   void addObject(int classNum,string name)
    {
        switch(classNum)
        {
        case 1:{classList.emplace_back(new Eclass(name));break;}
        case 2:{classList.emplace_back(new Fclass(name));break;}
        case 3:{classList.emplace_back(new Gclass(name));break;}
        case 4:{classList.emplace_back(new Jclass(name));break;}
        case 5:{classList.emplace_back(new Kclass(name));break;}
        case 6:{classList.emplace_back(new Iclass(name));break;}
        }

    }
    Aclass searchObject(string name)
    {
        for(int i=0;i<classList.size();i++)
        {
            cout<<classList[i]->getName();
            if(classList[i]->getName()==name)
            {
                return classList[i]
            }
        }
    }
 

funkcja ma za zadanie znaleźć obiekt o podanej nazwie i go zwrócić

dlaczego nie mogę zwrócić obiektu z vector?

1

Tutaj zwracasz przez kopię - czy masz zdefiniowany odpowiedni konstruktor kopiujący?

A może tak naprawdę chcesz zwrócić referencję? ;)

0

Nie mam , w której klasie należy go zdefiniować?

edit tak taki był pierwotny zamysł :)

0

powiem tak funkcja będzie później wykorzystywana do wyszukiwania obiektów i zmieniania ich zawartości. A Twoim zdaniem który sposób byłby najlepszy i najprostszy?

0

Już coś mam tylko natrafiłem na nowy problem, jak zrobić żeby ta sama funkcja zwracała różne typy obiektu. W jednym przypadku będzie to klasa C w innym klasa D itd
z góry dzięki za pomoc i przepraszam że tak truję w niedziele :)

1

Na sposoby są sposoby, ale... Zastanów się, czy Ci to potrzebne w ogóle. Czy musisz dostać się do metod klas potomnych, które nie są wirtualne? Możesz podać przykład?

2
Heptan napisał(a):

powiem tak funkcja będzie później wykorzystywana do wyszukiwania obiektów i zmieniania ich zawartości. A Twoim zdaniem który sposób byłby najlepszy i najprostszy?

To zależy. Pierwsze podstawowe pytanie, czy bierzesz pod uwagę fakt nieznalezienia takiego obiektu? Twoja implementacja wskazuje na to, że nie.

Heptan napisał(a):

Już coś mam tylko natrafiłem na nowy problem, jak zrobić żeby ta sama funkcja zwracała różne typy obiektu. W jednym przypadku będzie to klasa C w innym klasa D itd
z góry dzięki za pomoc i przepraszam że tak truję w niedziele :)

Koniecznie musisz rozróżniać typy? Przemyśl to raz jeszcze. Rozwiązaniem tutaj może być po prostu polimorfizm i prawidłowe wykorzystanie funkcji wirtualnych do określonych operacji.

0

To może przedstawię koncepcję całego projektu:
Mam jedną abstrakcyjną klasę bazową po której dziedziczy kilka klas również abstrakcyjnych. Z tych klas dziedziczą klasy "liście" i tylko one mogą tworzyć obiekty. Stworzyłem osobną klasę Panel która przechowuje obiekty klas "liści" w vector. Chcę umożliwić poprzez metody tej klasy (Panel) dodawanie usuwanie oraz modyfikowanie obiektów klas "liści" dodanych do vectora.

0
#include <iostream>
#include <string>
#include <vector>
#include "Aclass.h"
#include <memory>

using namespace std;



class Panelclass
{
private:
    vector <unique_ptr<Aclass>> classList;

public:
   void addObject(int classNum,string name)
    {
        switch(classNum)
        {
        case 1:{classList.emplace_back(new Eclass(name));break;}
        case 2:{classList.emplace_back(new Fclass(name));break;}
        case 3:{classList.emplace_back(new Gclass(name));break;}
        case 4:{classList.emplace_back(new Jclass(name));break;}
        case 5:{classList.emplace_back(new Kclass(name));break;}
        case 6:{classList.emplace_back(new Iclass(name));break;}
        }

    } 

ok już rozwiązałem problem z wyszukiwaniem, po prostu będe zwracał index w vector. Ale żeby nie było za dobrze to wrócił mi natomiast błąd kompilacji przy dodawaniu nowego obiektu wyskakuje error"Aclass is anbiguos base of Fclass" co jest źle w tym kodzie ?

0

Teraz problem leży po stronie hierarchii dziedziczenia Twoich klas - dziedziczysz coś więcej niż jeden raz. Zamieść kod poglądowy ilustrujący tę hierarchię wtedy będzie nam łatwiej pomóc.

0

hierarchia jest trochę rozbudowana

class Aclass
{
public:
virtual string getClassname();
virtual string getName();
virtual  string getString();
virtual void setClassName(string AclassName);
virtual void setInfo(string aInfo);
};

class Bclass
: public Aclass
{
public:
virtual string getClassname();
virtual string getName();
virtual  string getString();
virtual void setClassName(string AclassName);
virtual void setInfo(string aInfo);
};

class Cclass
: public Aclass
{
public:
virtual string getClassname();
virtual string getName();
virtual  string getString();
virtual void setClassName(string AclassName);
virtual void setInfo(string aInfo);
};

class Dclass
: public Aclass
{
public:
virtual string getClassname();
virtual string getName();
virtual  string getString();
virtual void setClassName(string AclassName);
virtual void setInfo(string aInfo);
};

class Eclass
: public Bclass
{
private:
    string name;
    string className;
    string info;
public:
    string getName();
    string getClassname();
    Eclass(string name);
    string getString();
    void setClassName(string AclassName);
    void setInfo(string aInfo);
};

class Fclass
: public Bclass,public Cclass
{
private:
    string name;
    string className;
    string info;
public:
    string getName();
    string getClassname();
    Fclass(string name);
    string getString();
    void setClassName(string AclassName);
    void setInfo(string aInfo);
};


class Gclass
: public Cclass
{
private:
    string name;
    string className;
    string info;
public:
    string getName();
    string getClassname();
    Gclass(string name);
    string getString();
    void setClassName(string AclassName);
    void setInfo(string aInfo);
};


class Hclass
: public Dclass
{
    public:
virtual string getName();
virtual string getClassname();
virtual string getString();
virtual void setClassName(string AclassName);
virtual void setInfo(string aInfo);
};

class Iclass
: public Dclass
{
private:
    string name;
    string className;
    string info;
public:
    string getName();
    string getClassname();
    Iclass(string name);
    string getString();
    void setClassName(string AclassName);
    void setInfo(string aInfo);
};
 
0

Jeżeli w main tworze obiekt to idzie bez problemu dopiero gdy tworzę go w vector to nie działa

dokładnie takie komunikaty wyskakują gdy próbuję to stworzyć w panel
<image>68523939f2.png</image>

1

Teraz już wszystko jasne. Błąd Aclass is an ambiguous base of Fclass bierze się stąd:

class Aclass {};
class Bclass : public Aclass {};
class Cclass : public Aclass {};
class Fclass : public Bclass, public Cclass {};

możesz ten problem rozwiązać dodając słówko virtual:

class Aclass {};
class Bclass : virtual public Aclass {};
class Cclass : virtual public Aclass {};
class Fclass : public Bclass, public Cclass {};

albo raz jeszcze przemyśleć tę hierarchię.

0

Oki już działa dzięki bardzo :)

PS dlaczego same wirtualne metody nie wystarcza?

1
Heptan napisał(a):

Oki już działa dzięki bardzo :)

PS dlaczego same wirtualne metody nie wystarcza?

Klasy B i C dziedziczą po wspólnej klasie bazowej A, a te są dziedziczone przez kolejną czyli F.
Zachodzi niejasność, poprzez którą klasa F ma dziedziczyć klasę A.

Metody wirtualne rozwiewają problem użycia metod, a tutaj potrzebujesz wirtualnego dziedziczenia klas.

0

AA już rozumiem dzięki wszystkim za pomoc temat do zamknięcia ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1