überladen von virtuelle methoden

AlexanderKiebler

Grünschnabel
Hi
Mich würde interessieren, ob man generell virtuelle Methoden überladen kann.
Vroweg, mir gelingt es nicht,
Ich würde gene eine Klasse zum arbeiten mit PGM Formaten schreiben.
Dabei hat das PGM Format mehrere Versionen (Binaer, ASCII, RGB und Graustufen)
Die Klasse soll sich für den Benutzer versionsunabhängig verhalten. Hierzu wollte ich eine Schnittstelle definieren (Virtuelle klasse) und sämtliche Versionen davon ableiten.
Jetzt ist es so, daß die Übergabaparameter für die Funktionen, welche auf die Daten der Klassen zugreifen davon abhängig sind, ob sie RGB oder Gray sind. In Folge dessen müßte ich die virtuellen Methoden der Vaterklasse überladen.
Ich habe im unteren Beispiel die Überladene Funktion rot markiert.

Code:
template<class kind_pgm> class pgm
{
    private:
        //Jedes pgm Objekt ist mit dinem Dateinamen verkuepft, aus welchem gelesen, oder in 
        //welchen geschrieben wird
        std::string dateiname;                                //Der name der Datei
        
        //Die von Sun Microsystems spezifizierten Daten fuer den header des PGM Formates
        int size_x;                                    //Größe in x-Richtung (Bildbreite)
        int size_y;                                    //Größe in y-Richtung (Bildhöhe)
        std::string formatken;                                //Speicher für die Formatkennung
        int dynamic_range;                                //Maximale Aussteuerung

    public: 
        //Konstruktor initialisiert den Dateikopf
        pgm(std::string dat_nam,int size_x,int size_y,std::string formken);        //Konstruktor
        //Der Destruktor der Basisklasse muß hier virtuell sein, damit destruktoren von abgeleiteten
        //klassen aufgerufen werden.
        virtual ~pgm()=0;                                //Destruktor 
        std::string get_dat_nam(void);                            //Gibt dateiname zurück
        int get_size_x(void);                                //gibt size_x zurück
        int get_size_y(void);                                //gibt size_y zurück
        std::string get_format(void);                            //gibt die Formatkennung zurück

        //Datei öffnen
        //Spätes Binden der Methoden --virtual
        //virtual bool write_to_hdd()=0;                        //Schreibt die Daten auf die Harddisk
        //virtual bool reade_from _hdd()=0;                        //Holt die Daten von der Festplatte
        virtual void read_head(void) throw(pgm_err)=0;                    //Kopf lesen
        

        //Datenmanipulationen
        virtual void set_akt_pix(int Breite,int Hoehe) throw(pgm_err)=0;        //Setzt aktuelle Pixel Postition
        virtual void next_akt_pix(void) throw(pgm_err)=0;                //Nächstes Listenelement 
        virtual kind_pgm get_pix(void)=0;                        //Gibt das aktuelle Pixel zurück
    //    virtual    void write_pix(kind_pgm iss)=0;                        //Schreibt ein aktuelles Pixel
        virtual void write_pix()=0;
        virtual void append_pix(kind_pgm iss) throw(pgm_err)=0;                //Hängt ein Pixel an die Liste an
        //virtual std::ostream& operator << (pgm<kind_pgm>)=0;                //Ausgabe stream Operato
};
 


template<class kind_pgm> class pgm_p2 : public pgm<kind_pgm>
{
    private:
    
        pgm_grau<kind_pgm> *data;                        //Die graustufendaten
        pgm_grau<kind_pgm> *pos_ptr;                        //Pointer auf aktuelles Element der Liste
        void rek_clear_list(pgm_grau<kind_pgm> *dat);                //Rekursives löschen einer Liste

    public:
         pgm_p2(std::string dat_nam,int size_x,int size_y,std::string formken,kind_pgm iss);        //Konstruktor
         ~pgm_p2();                                            //Destruktor
        
        //Datei öffnen
        virtual void read_head(void) throw(pgm_err);                //Liest den Header

        //Datenmaipulation
        virtual void next_akt_pix(void) throw(pgm_err);                //Nächstes Listenelement als aktuelles Pixel
        virtual void set_akt_pix(int Breite, int Hoehe) throw(pgm_err);        //Setze aktuelle Pixelposition
        virtual kind_pgm get_pix(void);                        //Gibt pixel zurück auf welches pos_ptr zeigt
      virtual void write_pix(kind_pgm iss);                    //Schreibt Pixel, auf welches pos_ptr zeigt
        virtual void write_pix();
         virtual void append_pix(kind_pgm iss) throw(pgm_err);            //Hängt ein Pixel an die Liste an
        //virtual std::ostream& operator<<(pgm_p2<kind_pgm> &s);            //Ausgabe streamen
};
 
Zuletzt bearbeitet:
Hi.

Was meinst du mit "es gelingt nicht"? Fehlermeldungen? Warum hast du die Deklaration der ersten Überladung auskommentiert?

Man kann Methoden einer Klasse überladen. Diese Methoden dürfen auch virtuell sein.

Gruß
 
Hi deepthroat
Mein Compiler meckert wenn ich versuche den Quelltext zu compilieren.
Da die Fehlermeldungen für beide Überladungen die Selben sind, habe ich die eine auskommentiert, damti das Problem übersichtlicher wird.
Ich bin der Meinung daß spätes Binden so nicht funktioniert.
Mein compiler meint:
local host# make all
g++ -g -c main.cpp -o main.o
main.cpp: In function »int main()«:
main.cpp:50: Fehler: keine passende Funktion für Aufruf von »pgm<unsigned char>::write_pix(char)«
pgm.h:77: Anmerkung: Kandidaten sind: void pgm<kind_pgm>::write_pix() [with kind_pgm = unsigned char]
make: *** [main.o] Fehler 1
Der Zugriff aus der main.cpp schaut folgender masßen aus:
PHP:
int main(void)
{

pgm<unsigned char> *Bilder[10];




Bilder[0]=new pgm_p2<unsigned char>("neue Datei",5,5,"P2",'a');
int x=0;
int y=0;
int i=0;

for(i=1;i<(Bilder[0]->get_size_x()*Bilder[0]->get_size_y());i++)
{
	try{	
		Bilder[0]->append_pix('a'+i);
	}
	catch(pgm_err & s)
	{
		std::cout << s.what;
	}
}



Bilder[0]->set_akt_pix(0,0);
Bilder[0]->read_head();

for(y=0;y<(Bilder[0]->get_size_y());y++)
{
for(x=0;x<(Bilder[0]->get_size_x());x++)
{

	try{
		//Bilder[0]->set_akt_pix(x,y);
		
		std::cout << "  Dateiname: " << Bilder[0]->get_dat_nam();
		std::cout << "  Breite: " << Bilder[0]->get_size_x(); 
		std::cout << "  Bildhoehe: " << Bilder[0]->get_size_y();
		std::cout << "  Format: " << Bilder[0]->get_format();
		std::cout << "  Datum: " << Bilder[0]->get_pix();
		
		std::cout << "\n";
		Bilder[0]->write_pix('a');
		Bilder[0]->next_akt_pix();
		}
	catch(pgm_err & s)
	{
			std::cout << s.what;
	}
}
std::cout << "\n\n-------------------------------------------------------------------\n\n";
}

delete Bilder[0];


return(0);


}
 
Zuletzt bearbeitet:
Hi deepthroat
Mein Compiler meckert wenn ich versuche den Quelltext zu compilieren.
Da die Fehlermeldungen für beide Überladungen die Selben sind, habe ich die eine auskommentiert, damti das Problem übersichtlicher wird.
Ich bin der Meinung daß spätes Binden so nicht funktioniert.
Mein compiler meint:
Code:
local host# make all
g++ -g -c main.cpp -o main.o
main.cpp: In function »int main()«:
main.cpp:50: Fehler: keine passende Funktion für Aufruf von »pgm<unsigned char>::write_pix(char)«
pgm.h:77: Anmerkung: Kandidaten sind: void pgm<kind_pgm>::write_pix() [with kind_pgm = unsigned char]
make: *** [main.o] Fehler 1
Es gibt offenbar keine Methode die ein Argument erfordert. Das ist ja auch logisch, da du diese Methode auskommentiert hast.

Wie ist die Ausgabe wenn beide Methoden in der pgm Klasse deklariert sind?

Gruß
 
Sorry da ist ein Missverständnis aufgetreten.
Die Methode nach der mein compiler sucht, habe ich nachträglich in die Basisklasse mit eingebaut, um das ganze wieder zunm laufen zu bringe. So würde es funktionieren.
Wäre aber nicht zweckdienlich. Ich bräuchte für jede neue Version des PGM Formates eine neue Funktion. Ich hatte gehofft, daß es auch ohne die geht.
Gruß
 
Sorry da ist ein Missverständnis aufgetreten.
Die Methode nach der mein compiler sucht, habe ich nachträglich in die Basisklasse mit eingebaut, um das ganze wieder zunm laufen zu bringe. So würde es funktionieren.
Wäre aber nicht zweckdienlich. Ich bräuchte für jede neue Version des PGM Formates eine neue Funktion. Ich hatte gehofft, daß es auch ohne die geht.
Nein, eine Methode aufrufen, die nicht deklariert ist geht nicht.

Evtl. wäre hier aber die Anwendung des Zustand-, Strategie- und/oder Schablonen-Designmusters ganz hilfreich.

Gruß
 
Zurück