Dziwny problem z map

0

Mam klase:

class Model
{
	map<string,Material> materials; 
	map<string,Material>::iterator it;
	Vertex vTab[100000];
	Vertex vnTab[100000];
	Face fTab[100000];
public:
	Model(string obj);
	void Draw();
};

i w klasie:

class GraphicEngine
{
public:
	World* world;
	map<string,Model> objectsModels; 
	map<string,Model>::iterator it;

	GraphicEngine(World* w);
	void LoadModels();
private:
};

funckje:

void GraphicEngine::LoadModels()
{
	Model mCar("bmw");
	string name = "bmw";
	pair<string,Model> para = make_pair(name,mCar);
	objectsModels.insert(para);

}

bład komilacji to:

Error 1 error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'

wystraczy ze zakomentuje 2 wiersze kodu:

pair<string,Model> para = make_pair(name,mCar);
objectsModels.insert(para);

I bład znika.
Naprawde dziwne. Prosze was o pomoc.

0
Vertex vTab[100000];
Vertex vnTab[100000];
Face fTab[100000];

Radykalnie :> Może na vectory to zamień. Sprawdź czy masz zrobione wszystkie niezbędne operatory przypisania i ctor'y kopiujące (głównie chodzi o Vertex i Face).

0
class Vertex
{
public:
	float x;
	float y;
	float z;
};

class Face
{
public:
	int v1;
	int v2;
	int v3;
	int v4;
	int vn1;
	int vn2;
	int vn3;
	int vn4;
	int count;
	std::string mtl;
    Face();	
};

Zbytnio nie rozumiem. Czego mi brakuje ?

0

Komunikat mówi, że próbujesz wykonać konstruktor (prawdopodobnie kopiujący) klasy std::basic_ios<_Elem,_Traits>::basic_ios
a jest on prywatny (ta klasa nie powinna być kopiowana).

Wrzuć cały komunikat (brakuje czym jest _Elem). Zakładam, że to char.

pair<string,Model> para = make_pair(name,mCar);

Tu jest kopiowanie. Kopiowany jest też Model. Jak jest kopiowany model to są kopiowane jego składowe. W szczególności te mapy stringów w materiały. Czyli wywołujesz konstruktor kopiujący klasy Material.

Strzelam, że trzymasz tam jako pole jakiś strumień (wartość). Zmień to na wskaźnik i będzie good ;-)

To jak wróżenie z fusów ;-D Daj więcej kodu. Np. tyle, żebym mógł skompilować i dostać ten błąd u siebie.

0

Zmień to na wskaźnik i będzie good

No nie do końca good, bo kto będzie odpowiedzialny za zwolnienie tego wskaźnika? Musi przeładować operator przypisania i konstruktor kopiujący.

0
class Material
{
public:
	std::string name;
	float Ns;
	Vector Ka;
	Vector Kd;
	Vector Ks;
};

i pełny bład:
Error 4 error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>' d:\programy\microsoft visual studio 9.0\vc\include\fstream 934 Full destruction

Nie rozumiem co jest złego w tym, ze uzywam string.

0

Sprawdź taki kod:
Vector a;
Vector b = a;
lub pokaż klasę Vector.

Jeżeli usunę pola Ka Kd i Ks to u mnie się kompiluje.

String nie ma nic do tego. Dobrze, że z niego korzystasz.

Jeżeli korzystasz z jakiegoś Visuala to spróbuj go wyłączyć i włączyć, kompilować projekt od podstaw i różne tego typu rzeczy.

0

Czegoś nam nie powiedziałeś pokazałeś!
przeczytaj dokładnie błąd który podałeś:
error C2248: 'std::basic_ios<_Elem,_Traits>::basic_ios' : cannot access private member declared in class 'std::basic_ios<_Elem,_Traits>'
oznacza, że kompilator nie może dostać się do prywatnego elementu kasy std::basic_ios<_Elem,_Traits>
No i tu moje zdziwienie! Skąd std::basic_ios? Przecież jest to szablon związany z obsługa strumieni danych (np. plików), a twój kod, który podałeś, nie wykazuje nigdzie miejsca wykorzystywania strumieni, więc czegoś nam brakuje żeby ci pomóc.
Zresztą patrzę na pełniejszy opis błędu i już widzę że coś pomieszałeś z plikami bo pojawia się odnośnik do fstream.

0

Tutaj jest cały kod:

http://chomikuj.pl/edwin_/problem+map.zip

haslo: map

Mam nadzieje ze pomoże

0

Oszukałeś. Nie podałeś pełnego kodu klasy Model wcześniej. Ma ona pole Parser. Parser ma pola:

	fstream inOBJ;
	fstream inMTL;

Jeżeli kopiujesz Model to kopiujesz też Parser, więc kopiujesz strumienie fstream, a tego nie wolno robić (bo mają prywatny konstruktor: dziedziczą po basic_ios).

Najprostsze rozwiązanie jakie ja widzę to zamiast pamiętać strumienie, pamiętać tylko nazwy plików. Ewentualnie możesz pamiętać wskaźniki. Tylko nie używaj new do ich inicjalizacji. Powinny wskazywać na zmienną automatyczną gdzieś niżej na stosie.

To najprostsze rozwiązanie - tak, żebyś nie musiał zmieniać dużo kodu. Moim zdaniem jest błe (bardzo złe). Dlaczego, w ogóle, model ma tego typu pole? Nie sądzisz, że to dziwne. Argument z nazwą pliku możesz przekazać np. przez wartość (lub referencję do stałej) metody ładującej model z pliku.

edit:
Używaj #ifndef #define #endif w plikach nagłówkowych. Niektóre nie mają.

edit2:
Możesz jeszcze utworzyć konstruktor kopiujący i operator przypisania w klasie Model. Tylko musisz wymyślić jakieś sensowne zachowanie dla kopiowania Parsera.

0

Popraw tak:

// plik Model.h
#include "parser.h"
class Model
{
	map<string,Material> materials; 
	map<string,Material>::iterator it;
	Vertex vTab[100000];
	Vertex vnTab[100000];
	Face fTab[100000];
	int vIndex;
	int vnIndex;
	int fIndex;
	// to do skasowania: Parser p;

	void CopyTable( Parser& p); // tu dodatkowy parametr '&' jest KONIECZNE
public:
	Model(string obj);
	void Draw();
};

// plik Model.cpp
Model::Model(string obj)
{
	Parser p; // nowa linijka obiekt automatyczny
        p.ParseObj(obj);
	vIndex = p.vIndex;
	vnIndex = p.vnIndex;
	fIndex = p.fIndex;
	CopyTable( p ); // nowy parametr
}
....
void Model::CopyTable( Parser& p )
{
  .... // reszta bez zmian

Nie udzielam gwarancji bo nie analizowałem tego kodu dokładnie :P .

0

Spróbowałem to naprawić. Teraz mam błąd wykonania... Czego nie rozumiem ??

http://chomikuj.pl/edwin_/map+problem+2.zip

haslo map

Dziękuje za okazaną mi pomoc.

0

No to debugger do ręki i do dzieła. Jeśli wszystko dostaniesz na tacy to niczego się nie nauczysz.

0

Oj cieknie cieknie. Brak destruktorów, które zwalniają pamięć (vide klasa Console).

I tu cieknie:

Model* Parser::LoadModel(string name)
{
	[...]
	Model* m = new Model();
	[...]
	return m;
}

void GraphicEngine::LoadModels()
{
	Model* mCar = parser->LoadModel("bmw13");
	string name = "bmw";
	pair<string,Model> para = make_pair(name,*mCar); // WHY WHY WHY WHY ???
	objectsModels.insert(para);
} //<---- a co z mCar????

To dość poważny wyciek zważywszy, że Model zawiera takie cudo:

Vertex vTab[100000];
Vertex vnTab[100000];
Face fTab[100000];

Policzmy: (12*2 (Vertex) + 64(Face)) * 100000 = 8,8MB (bez materials, które zawiera kopie Material - ~60 bajtów każdy). Niemało...

Ogólnie w tym twoim kodzie za dużo jest kopiowania obiektów.

PS. Oczywiście to nie jest rozwiązanie problemu z błędami wykonania.

0

Zgadza się. Wszędzie cieknie. Destruktorami zajmuje sie na końcu pisania programu. To aż taki zły nawyk?

0
edwin napisał(a)

Zgadza się. Wszędzie cieknie. Destruktorami zajmuje sie na końcu pisania programu. To aż taki zły nawyk?

Tak, bo mozesz o ktoryms zapomniec.

0

Jak zwykle bład jest dotyczy tych samych wierszy kodu:

pair<string,Model> para = make_pair(name,*mCar);
objectsModels.insert(para);

Czegoś nie wiem. Powiedzcie jaki rozdział ksiązki z c++ przeczytać aby zrozumieć skąd bierze się ten bład.

0

Następny wyciek:

void Parser::ParseMtlLine(fstream& in)
{
	[...]
	
	else if(T.compare("Ka") == 0)
	{
		Vector* v = new Vector();
		ParseVector(in,v);

		materials[currentLoadingMtl].Ka.x = v->x;
		materials[currentLoadingMtl].Ka.y = v->y;
		materials[currentLoadingMtl].Ka.z = v->z;
	} //<--- a co z 'v'???
	else if(T.compare("Kd") == 0)
	{
		Vector* v = new Vector();
		/* reszta jak wyżyej */
	} //<--- a co z 'v'???
	else if(T.compare("Ks") == 0)
	{
		Vector* v = new Vector();
		/* reszta jak wyżyej */
	} //<--- a co z 'v'???
	
	[...]
} 

No i dlaczego v jest tworzony dynamicznie?

Tu coś dziwnego:

void Parser::CopyTable(Model* m)
{
	[...]
	
	for(int i = 0; i < fIndex; i++)
	{
		[...]
		
		m->materials = materials; //<--- na pewno tutaj???
		
		[...]
	}
}

Nie rozumiem po co Parser trzyma to:

map<string,Material> materials; 
map<string,Material>::iterator it;
Vertex vTab[100000];
Vertex vnTab[100000];
Face fTab[100000];
int vIndex;
int vnIndex;
int fIndex;

byłoby znacznie efektywniej i logiczniej, gdyby parser od razu ładował klamoty do Model.

0

Tak.... Klasa model jest za duża i powoduje przepełnienie stosu .... eh... teraz to wydaje sie takie oczywiste.

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