Przekazywanie wektora do funkcji przez referencję

0

Witam,
Mam 3 klasy:
Space.h

class Space
{
protected:
	int boardSize;
	struct Position {
		size_t x, y;
	};
	Position coordinate;
	std::vector<Position>collectionXY;
public:
	Space();
	~Space();
};

Stream.h

class Stream : private Space
{
public:
	Stream();
	~Stream();
	void ReadSampleXY(std::string &d);
	void ReadGroupXY(std::string &d);
	void ReadInitialData(std::string d);

};

Tree.h

class Tree : private Space
{
private:
	Node root;
	Node* chosenNode;
	std::vector<Node*>previousNodes;
public:
	Tree(int size, std::vector<Position>&collection);
	~Tree();
	//void checkMovePossibilities(std::vector<Position>&collection);

};

Cała rzecz polega na tym, że do funkcji klasy Stream przekazuję ciąg znaków pobranych z bufora. Następnie ciąg ten analizuję, a wyniki z tych 3 funkcji zawsze w postaci współrzędnych zapisuję do wektora collectionXY. Teraz wektor ten chcę przekazać przez referencję zarówno do konstruktora klasy Tree, jak i do funkcji checkMovePossibilities klasy Tree i za bardzo nie wiem jak to zrobić aby nie naruszyć enkapsulacji danych. Bo mógłbym oczywiście w klasie Space zmienną std::vector<Position>collectionXY zrobić publiczną, ale to nie jest chyba dobre rozwiązanie. To samo tyczy się zmiennej boardSize której wartość z obiektu klasy Stream będę musiał przekazać do konstruktora klasy Tree.
Jedyne co chodzi mi po głowie to publiczne metody Get, choć dla wektora taka metoda pewnie musiałaby wyglądać tak jak dla tablicy czyli wkaźnik na 1 element + wielkość wektora, albo zaprzyjaźnić konstruktor Tree i metodęcheckMovePossibilities z klasą Stream.

0

Zastanów się czy w ogóle albo czy w obu przypadkach musisz użyć prywatnego dziedziczenia. Takie dziedziczenie zazwyczaj można zastąpić kompozycją. Cytując Scotta Meyersa:

"Private inheritance means is-implemented-in-terms of. It’s usually inferior to composition, but it makes sense when a derived class needs access to protected base class members or needs to redefine inherited virtual functions."

Nie używasz funkcji wirtualnych, więc może Tree wcale nie musi dziedziczyć po Space. W końcu i tak chcesz przekazać vector<Position> do funkcji checkMovePossibilities więc może z poziomu Tree nie potrzebujesz dostępu do collectionXY.

0
GutekSan napisał(a):

Nie używasz funkcji wirtualnych, więc może Tree wcale nie musi dziedziczyć po Space. W końcu i tak chcesz przekazać vector<Position> do funkcji checkMovePossibilities więc może z poziomu Tree nie potrzebujesz dostępu do collectionXY.

Ok. W klasie Tree nie potrzebuję dostępu do collectionXY. Potrzebuję tylko dostępu do wartości vector<Position>collectionXY z obiektu klasy Stream. W klasie Tree potrzebuję więc tylko stukturę Position.

class Tree 
{
private:
	Node root;
	Node* chosenNode;
	std::vector<Node*>previousNodes;
	struct Position {
		size_t x, y;
	};
public:
	Tree(int size, std::vector<Position>&collection);
	~Tree();
	void createTreeTier(Node* chosen);
	void checkMovePossibilities(std::vector<Position>&collection);

};

Dziedziczenie prywatne w klasie Stream dałem jako relację has-a. Kompozycja (która w moim rozumieniu kompozycji zmienia tylko to, że nie stworzę obiektu klasy Space bez obiektu klasy Stream, jako zasadę że A korzysta z B, B nie może istnieć bez A) nie rozwiązuje problemu przekazywania vector<Position> między obiektami klas Stream i Tree. Zarówno w dziedziczeniu prywatnym i kompozycji dalej vector<Position>collectionXY będzie w klasie Stream polem prywatnym.

1

Dziedziczenie prywatne! Po co?
To pytanie to jest typowy problem XY.
Może lepiej od początku opisz co robisz, jaki problem ma rozwiązywać twój kod.
Dopiero potem jak próbujesz rozwiązać ten problem,
a dopiero na końcu jaki jest problem z twoim rozwiązaniem.

To mi wyglądana typowy problem internalizacji (wczytywania jakiś danych), który rozwiązujesz w jakiś dziwny sposób.

0

Kurcze, jest to fragment większej całości. Będzie to gra. I muszę stworzyć drzewo ze stanem gry.
Problem polega na tym że wczytuję dane jako string i muszę je zamienić na wspórzędne. Bedą to wspórzędne z zajętymi polami planszy. Współrzędne te przechowuję w wektorze collectionXY. Zrobiłem pomocniczą klasę Space, aby rozgraniczyć pracę na stringach i danych już przetworzonych do poprawnych typów. Wektor collectionXY z klasy Stream dziedziczącej po klasie Space muszę przekazać do konstruktora klasy Tree aby prawidłowo zainicjować stan gry, a w kolejnych ruchach odpowiednio tworzyć drzewo i węzły w tym drzewie, odpowiadające możliwym ruchom (metoda void checkMovePossibilities(std::vector<Position>&collection)). I mam pytanie jak przekazać wektor vector<Position>&collectionXY z obiektu klasy Stream (klasy która służy jedynie do odszyftrowania stringa) do metody bądź konstruktora klasy Tree, gdzie stworzę węzły zawierające dane z collectionXY

Node.h

class Node {
private:
	std::vector<Node>movePossibilities;
	int weight;
	struct Position
	{
		size_t x, y;
	};
	struct Rectangle 
	{
		Position firstField;
		Position secondField;
	};
	Rectangle rectangle;
public:
	Node();
	Node(Node* parent, Position &pos1, Position &pos2);
	~Node();
};
0

Nadal się skupiasz na problemie Y, którego nie rozumiem.

Tu masz przykład rozwiązania problemu X za pomocą boost serialization : https://4programmers.net/Forum/C_i_C++/300163-pytanie_o_strukture_danych_w_pliku_txt?p=1423367#id1423367
https://wandbox.org/permlink/jcIWU4toEbdfL4VM
Tanim kosztem można zorganizować zapis i odczyt danych do pliku w postaci xml-a lub innego typu archiwum.
Zapewne to jest za duża armata dla ciebie, ale jeśli jesteś na wczesnym etapie warto się zainteresować.

0

Oj, dopiero jestem na początku drogi z C++, nie znam jeszcze STL, nie mówiąc o boost.
Najprociej jak potrafie:

class Dane {
private:
	std::vector<Wspolrzedne>dane;
public:
	void odczytajDane(std::string ciag_danych);  //< ----pobiera stringa i zapisuje do wektora vector<Wspolrzedne>dane
};

class Szablon {
public:
	void wczytajDane(std::vector<Wspolrzedne>&d);
};


int main() {
	Dane moje_dane;
	moje_dane.odczytajDane("X1xY1_X2xY2_X3xY3");

	Szablon moj_szablon;
	szablon.wczytajDane(????);	//<------- jak wczytać wartości z vector<Wspolrzedne>dane;


	return 0;
}
0

Opcje:

  1. Obiekt klasy Dane zwraca Ci vector<Position>, który potem przekazujesz do obiektu Szablon albo Tree. W tym sensie obiekt dane nie trzyma danych tylko je parsuje z jednego formatu na inny:
Dane moje_dane;
vector<Position> vp;
moje_dane.odczytajDane("X1xY1_X2xY2_X3xY3", vp); // vp przekazywane przez referencje
// alternatywnie możesz korzystając z r-value reference zrobić:
// moje_dane.odczytajDane("X1xY1_X2xY2_X3xY3");
// vp = moje_dane.zwrocDane();

Szablon moj_szablon;
szablon.wczytajDane(vp);
  1. Jesli klasa Dane ma faktycznie opakowywac vector i te dane trzymac, dodajesz konieczne akcesory i przekazujesz obiekt dane do funkcji Szablon::wczytajDane(Dane&).
1

@mlp99: Słuchaj, nie chcę Cię zniechęcać, ale bierzesz się za robienie poważnych rzeczy w C++ bez znajomości STLa...? Poświęć trochę czasu i energii poznaniu przynajmniej podstaw STLa, opłaci się!

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