Objekt-Arrays mit CArray



  • Hi!

    Ich habe folgenden Code:

    /******************************************/
    class TDatabase: public CDatabase
    {
    public:
    	bool IsInUse();
    };
    
    typedef CArray<TDatabase, TDatabase&> cDatabase;
    
    /******************************************/
    class ODBC
    {
    public:
    TDatabase *ODBC::GetDatabase()
    {
    	TDatabase *retDatabase = NULL;
    	for (int i = 0; i < this->pDatabaseArray.GetSize(); i++)
    	{
    		//get all unused Database connections
    		if (!(this->pDatabaseArray->GetAt(i)).IsInUse())
    		{
    			if (retDatabase == NULL)
    			{
    				retDatabase = this->pDatabaseArray.GetAt(i);
    			}
    			else	//delete unused Database connections
    			{
    				delete &this->pDatabaseArray.ElementAt(i);
    				this->pDatabaseArray.RemoveAt(i);
    			}
    		}
    	}
    	return retDatabase;
    }
    private:
    	cDatabase pDatabaseArray;
    };
    
    typedef CArray<ODBC, ODBC&> cODBC;
    
    /******************************************/
    class Database
    {
    	cODBC pODBCArray;
    };
    

    Der Code ist natürlich nicht ganz vollständig, reich taber um mein Problem zu skizzieren:

    Meiner Meinung nach sollte das funktionieren, aber denkste, der Compiler schreit beim Übersetzen und ich verstehe nicht ganz warum:

    include\afxtempl.h(255) : error C2558: class 'ODBC' : Kein Kopierkonstruktor verfuegbar
    include\afxtempl.h(1566) : Bei der Kompilierung der Member-Funktion 'class ODBC __thiscall CArray<class ODBC,class ODBC &>::GetAt(int) const' der Klassenvorlage

    include\afxtempl.h(255) : error C2558: class 'TDatabase' : Kein Kopierkonstruktor verfuegbar
    include\afxtempl.h(1566) : Bei der Kompilierung der Member-Funktion 'class TDatabase __thiscall CArray<class TDatabase,class TDatabase &>::GetAt(int) const' der Klassenvorlage

    Wenn ich das TDatabase CArray aus dem ODBC Objekt entferne und einfach nur einen Pointer auf ein TDatabase einbaue funktioniert das ganze ODBC Konstrukt prima. Ich habe nun versucht statt cDatabase pDatabaseArray; cDatabase *pDatabaseArray; zu verwenden, aber dann bekomme ich beim Kompilieren immer noch folgende Fehlermeldung:

    include\afxtempl.h(255) : error C2558: class 'TDatabase' : Kein Kopierkonstruktor verfuegbar
    include\afxtempl.h(1566) : Bei der Kompilierung der Member-Funktion 'class TDatabase __thiscall CArray<class TDatabase,class TDatabase &>::GetAt(int) const' der Klassenvorlage

    Wie gesagt, ich verstehe nicht ganz warum der Code nicht kompilierbar ist. Kann mir das jemand erklären und weiss jemand was ich anders machen muss, damit es funktioniert, oder ist das so überhaupt nicht machbar? Danke!

    Sebo



  • CArray::GetAt() liefert eine Kopie des Array-Elements zurück, aber dazu braucht es den Copy-Ctor - und den liefert TDatabase anscheinend nicht (manche Klassen sind halt nicht kopierbar ;)). Versuch' mal, alle Vorkommen von GetAt() zu ersetzen durch ElementAt() - das liefert eine Referenz und kommt deshalb ohne Copy-Ctor aus.



  • Ja das weiss ich. Ich dachte nur, dass ich ElementAt() nur brauche wenn ich schreibend drauf zugreifen will und das mache ich ja. Ich probier's mal schnell aus ..... also ich habe nun alle GetAt() beider CArrays auf ElementAt() umgebaut (suchen-ersetzen), bekomme aber dieselben Fehlermeldungen ..... zweiter Versuch: nun habe ich statt cDatabase pDatabaseArray; cDatabase *pDatabaseArray; verwendet und es kommt nur noch folgender Fehler:

    include\afxtempl.h(255) : error C2558: class 'TDatabase' : Kein Kopierkonstruktor verfuegbar
    include\afxtempl.h(1566) : Bei der Kompilierung der Member-Funktion 'class TDatabase __thiscall CArray<class TDatabase,class TDatabase &>::GetAt(int) const' der Klassenvorlage

    Diesen Fehler bekomme ich aber einfach nicht weg - hab' ein bisschen "rumprobiert". 😞 Woran kann es nun noch liegen?

    Sebo



  • Du versuchst immer noch etwas nicht-kopierbares in deinem CArray untergebracht, da wird vermutlich jede Methode streiken, die aus irgendeinem Grund Array-Elemente kopieren will (GetAt() ist dafür natürlich der erste Kandidat). Eine Möglichkeit wäre es, deiner Klasse einen eigenen Copy-Ctor zu spendieren (ich bin mir allerdings nicht ganz sicher, ob dessen Basisklasse CDatabase da mitspielt), alternativ kannst du ein CArray<TDatabase*> verwenden (Pointer sind auf jeden Fall kopierbar).



  • Einleuchtend, ich weiss nun auch wo das Problem ist, die CArray.Add() Funktion macht intern eine Zuweisung und daran stört sich der Compiler. Ich weiss nur nicht wie ich das ändern soll, ich habe eher den Verdacht, dass das gar nicht geht. Mein Code:

    void ODBC::SetDatabase(TDatabase *value)
    {
    	this->pDatabaseArray->Add(*value);
    	this->pDatabaseArray->Add(TDatabase::TDatabase());     //funktioniert auch nicht
    }
    

    Jep, es liegt an CDatabase, logischerweise kann es nicht kopiert werden, weil es eine offene Verbindung zu einem DB Server inne haben kann. Test:

    typedef CArray<CDatabase, CDatabase&> cCDatabase;
    
    cCDatabase cdbase;
    cdbase.Add(CDatabase::CDatabase());
    

    > selber Fehler, funzt also nicht.

    Also Danke für die Hilfe, jetzt bin ich zwar gefrustet, aber auch schlauer. 😃

    Sebo



  • Wie ich vorhin schon sagte - verwende doch ein Array von TDatabase-Zeigern (die können kopiert werden, wenn es nötig wird) und kümmere dich selber um die Speicherverwaltung. (alternativ kannst du auch Smart-Pointer ala boost::shared_ptr verwenden)



  • Genau das habe ich auch gemacht, hat noch ein paar kleine Anpassungen gebraucht, funzt jezt aber prima. 🙂


Anmelden zum Antworten