Stworzenie tablicy, wektora w którym są dwa typy

0

Czy da się np. utworzyć kolekcję (tablicę, listę) figur - trójkątów i czworokątów w jednym wektorze, tablicy ?

2

Krótko: nie. Ale:

Jeżeli te klasy dziedziczą wspólny interfejs to wtedy można zrobić wektor wskaźników na tę klasę bazową. Dzięki polimorfizmowi będzie to działać.

Oczywiście można sobie wyobrazić jakieś wynalazki, które umożliwiałyby to bez polimorfizmu. Zapewne boost może w tym pomóc. Zazwyczaj jednak nie jest to potrzebne.

0

czyli zrobić oddzielny wektor dla trojkatow i czworokat

2

Są 2 wyjścia na takie sytuacje:
1 (prostsze) -> użyj czegoś takiego jak disjoint union, tj. albo ręcznie zaklepiesz jakiś eiter<left, right>, albo użyjesz jakiegoś gotowego, albo zaimitujesz to przy użyciu dziedziczenia.
2 (trudniejsze) -> użyj czegoś takiego jak heterogeneous list, z którą są 2 problemy:
a) sensownie zaimplementowana taka lista infekuje generalnie cały kod, w którym jest użyta, a to się robi z czasem brzydkie.
b) bezsensownie zaimplementowana taka lista, sprawia że kompilator jest bezuzyteczny i nie daje żadnej gwarancji co do tego jak działa.
(Tutaj jest to trochę bardziej wyjaśnione jak ktoś jest ciekawski: http://okmij.org/ftp/Haskell/HList-ext.pdf)

Tl;dr: Najbardziej idiomatyczn dla kodu OOPowego jest użycie dziedziczenia.

czyli zrobić oddzielny wektor dla trojkatow i czworokat

To akurat słaby pomysł z punktu logicznego, bo zakładam, że chcesz trzymać kolekcję figur i wykonywać jakieś operacje niezależnie od rodzaju figury? Jeśli tak i nie potrzebujesz, żeby to było mega cache friendly, to zrób dziedziczeniem.

0

Najlepiej zrobić tak, jak napisał @Endrju, by obie klasy dziedziczyły po wspólnej klasie bazowej.

Można też zrobić bez dziedziczenia - (void* + rzutowania) poniższy kod to bardziej jako ciekawostka (minus jest taki, że trzeba wiedzieć, który element, jest którego typu):

#include <iostream>

using namespace std;

class Triangle{
    public:
    void foo()
    {
        cout << "Triangle" << endl;
    }
};

class Rectangle{
    public:
    void foo()
    {
        cout << "Rectangle" << endl;
    }
};

int main()
{
   Triangle t1;
   Triangle t2;
   
   Rectangle r1;
   Rectangle r2;
   
   void* a[] = {(void*)&t1, (void*)&r1};
   
   (static_cast<Triangle*>(a[0]))->foo();
   (static_cast<Rectangle*>(a[1]))->foo();
   
   return 0;
}

3

Możesz użyć boost::variant, boost::any albo boost::fusion ale ja polecam boost::hana:

using namespace boost::hana;

struct Fish { std::string name; };
struct Cat  { std::string name; };
struct Dog  { std::string name; };

auto animals = make_tuple(Fish{"Nemo"}, Cat{"Garfield"}, Dog{"Snoopy"});
auto names = transform(animals, [](auto a) { return a.name; });

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