Elementfunktion sei in Klasse nicht deklariert



  • Zeile 310. Seh ich schon Ufos?



  • @Skym0sh0:

    Tut mir leid, als ich deinen Beitrag gelesen hatte, war es schon zu spät 😞
    Ja ich benutze die Libtiff



  • @MFK

    Vielen Dank, dass habe ich gleich mal geändert 😉
    (weiß garnicht, warum da nicht mal eine Warnung kam)

    Damit änderte sich aber leider nicht mein Problem 😞



  • MFK schrieb:

    Zeile 310. Seh ich schon Ufos?

    Möp. oO

    Ich hab per Textsuche das dezent überlesen 😣



  • Nur mal so aus der Luft gegriffen:

    Könnte es sein, dass du dein Projekt kompiliert hast, bevor du test() und invert() implementiert hast?

    Ansonsten kann ich mir nichts anderes vorstellen was an dem Code falsch sein könnte, sodass der Compiler eine derartige Fehlermeldung ausspuckt.



  • @hmhmhm:

    Also ich habe jetzt jede einzelne Komponente (ob .h oder .cpp) gespeichert und alles nochmal versucht zu kompilieren. Aber die Fehlermeldung ist leider nach wie vor noch die selbe. 😞



  • 'tschuldigung, umgekehrt:

    *könnte es sein, dass du test() und invert() implementiert hast, bevor du sie in der klasse deklariert hast?

    Und "uint16 long" hat echt keine Fehlermeldung rausgeworfen? Welche Compiler-Version von G++ hastn?



  • Xx_Mephisto_xX schrieb:

    Damit änderte sich aber leider nicht mein Problem 😞

    Wenn ich Header und Implementierung in ein File kopiere, kann ich (nachdem ich einen c'tor nach hinten in der Datei verschoben habe) alles kompilieren.

    Kompilierst Du das richtige? 🙂



  • Also meine gxx-Version:
    g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3

    und ich kompiliere wie folgt:

    g++ -Wall main.cpp image.cpp hist.cpp -ltiff -o ausgabe



  • Das ist zwar ein wenig wie Schnitzeljagd, aber bau doch mal einen ganz offensichtlichen Fehler ein.
    Z.B. ein unmotiviertes

    SCHIRSCHADENDUDEL

    mitten im Quelltext des Headers. Wenn das wirklich der Header ist, der eingebunden wird, fällt Dir das auf die Füsse.
    (Und ich denke der gepostete Header ist nicht der, den der Compiler sieht.)



  • g++ meinte ich statt gxx ^^

    Kann es sein, dass ich beim includieren etwas falsch mache?
    ich includiere "image.h" sowohl in der main.cpp als auch in der hist.h

    hier die hist.h:

    #ifndef HIST_H
    #define HIST_H
    
    #include "image.h"
    
    class HIST{
    public:
    
    HIST(IMAGE&);
    
     unsigned int GetHistBufferValue(int);
     unsigned int GetHistSize();
     int FindMax();
    
     void PrintHist();
    
     void test();
    
    private:
     IMAGE* img;
     unsigned long histSize;
     unsigned long *histBuffer;
    };
    
    #endif
    

    und die main.cpp (besteht mittlerweile aus auskommentierten Quelltexten)

    #include <iostream>
    #include <stdio.h>
    //#include <string.h>
    
    #include "image.h"
    #include "hist.h"
    
    using namespace std;
    
    int main(){
    return 0;
    }
    


  • SCHIRSCHADENDUDEL springt nun mitten aus meiner classIMAGE hervor 😉

    g++ -Wall main.cpp image.cpp hist.cpp -ltiff -o ausgabe
    In file included from main.cpp:5:0:
    image.h:83:1: Fehler: »SCHIRSCHADENDUDEL« bezeichnet keinen Typ
    image.cpp:405:20: Fehler: keine Elementfunktion »void IMAGE::invert()« in Klasse »IMAGE« deklariert
    image.cpp:406:18: Fehler: keine Elementfunktion »void IMAGE::test()« in Klasse »IMAGE« deklariert
    In file included from hist.h:4:0,
                     from hist.cpp:1:
    image.h:83:1: Fehler: »SCHIRSCHADENDUDEL« bezeichnet keinen Typ
    make: *** [all] Fehler 1
    


  • Solange du Includeguards hast, sollte beim Inkludieren nichts falsches passieren, und die hast du ja.

    Hast du zyklische Abhängigkeiten?
    A inkludiert B und umgekehrt (eventuell über mehrere Indirektionen)



  • Leider kommt jetzt meine c++-Unkenntnis zum tragen.
    Was versteht man unter einer Indirektion?
    Ich hatte mal etwas von einer Überladung des -> Operators gelesen. Ist es das?

    folgende include-beziehungen habe ich derzeit:

    main includiert : - image - hist
    hist includiert : - image

    Also wäre die Antwort A includiert B aber nicht umgekehrt



  • Mal abgesehen vom eigentlichen Problem (wo man im Moment nur raten kann, weil du kein vollständiges aber reduziertes Beispiel zeigst, was dieses Problem noch hat) möchte ich ein paar Takte zum Stil/Design sagen.

    Verwende Bezeichner wie "IMAGE", die nur aus Großbuchstaben bestehen, nur für Makros. Dann besteht auch keine Verwechslungsgefahr zwischen Makros und nicht-Makros. Das ist eigentlich Konvention so.

    class IMAGE
    {
    public:
      ...
    private:
      TIFF* image;
     
      char *imageName;
      uint16 *buffer;
     
      uint32 *width, *height;
      uint16 *bps, *spp;
     
      unsigned long *rowsps, *bufferSize;
      int *scanlineSize;
    

    Das ist sehr ungeschickt. Du musst mit deiner Klasse per eigenem Kopierkonstruktor, Destruktor und Zuweisungsoperator schon das dynamisch allozierte TIFF-Dingen verwalten. Das reicht eigentlich schon. Klassen zu bauen, die gleich ganz viele verschiedene Resourcen verwalten, sind fehleranfällig. Es besteht auch überhaupt keine Notwendigkeit in Deinem Fall den Rest auch per new anzulegen:

    class TiffImage
    {
    public:
      ...
    private:
      void* image;
    
      std::string filename;
      std::vector<uint16> buffer;
    
      uint32 width, height;
      uint16 bps, spp;
    
      unsigned long rowsps, bufferSize;
      int scanlineSize;
    

    Hier musst du dich im Prinzip nur noch um 'image' kümmern bzgl Freigabe/Kopieren. Die Typen der restlichen Datenelemente haben jetzt schon von Haus aus das richtige Kopierverhalten.

    Aus 'image' habe ich hier noch einen void*-Zeiger gemacht, damit du in diesem Header nicht den Tiff-Header inkludieren musst. In image.cpp brauchst du dann aber einen static_cast.

    Was ich nicht ganz so schön finde, ist, dass du all die möglichen Bildverarbeitungsalgorithmen als Elementfunktion in diese Klasse gepackt hast. Der C++-Weg sieht eher anders aus. Da verwendest du eine solche Klasse nur dazu, um Bilder per Objekte zu speichern. Die Algorithmen kann man dann als Funktionstemplate aufschreiben. Als Bindeglied muss man ggf andere Konzepte einführen, so ähnlich wie es in der Standardbibliothek die Iteratoren gibt. Aber das ist nur ein Tipp für die Zukunft.



  • Xx_Mephisto_xX schrieb:

    Leider kommt jetzt meine c++-Unkenntnis zum tragen.
    Was versteht man unter einer Indirektion?
    Ich hatte mal etwas von einer Überladung des -> Operators gelesen. Ist es das?

    folgende include-beziehungen habe ich derzeit:

    main includiert : - image - hist
    hist includiert : - image

    Also wäre die Antwort A includiert B aber nicht umgekehrt

    Richtig.

    Mit Indirektion meine ich sowas:
    A includiert B
    B inkludiert C
    C inkludiert D
    und D inkludiert A

    A --> B
    ^     |
    |     v
    D <-- C
    // anstatt
    A <-> B
    

    Das ist halt wenn die Abhängigkeiten nicht direkt sind, sondern über ein paar Umwege (sprich andere Dateien)



  • @ krümelkacker

    Vielen Dank für deine Ratschläge.

    bezüglich der Geschichten mit "new": ich orientierte mich da an dem Buch "c++ in 21 Tagen" (Einführung in Kopierkonstruktoren).

    Der Vorschlag mit den Funktionstemplate's klingt interessant.
    Zwar tun sich da ein paar Fragezeichen auf, aber die werden sich hoffentlich mit einer Rechercheaufgabe abwenden lassen. 🙂

    Ich werde versuchen deine Vorschläge in die Tat umzusetzen 😉

    Ich hätte da an dieser Stelle aber eine Frage bezüglich des void-Zeigers image.

    bisher brauche ich den TIFF-Zeiger diesen für folgende Zeile:
    (Ausschnitt des Konstruktors)

    image = TIFFOpen(filename, "r");
    

    laut LIBTiff ist TIFFOpen wie folgt definiert:

    TIFF* TIFFOpen(const char *filename, const char *mode)
    

    würde mir das dann nicht Probleme machen?



  • @Skym0sh0

    Ah, ok, klingt schwer nach einer bösen Dauerschleife.^^

    Mmh, in meiner hist.cpp:

    HIST::HIST(IMAGE& inputImg){
     histSize = pow(2,inputImg.GetBPS());
     histBuffer = new unsigned long[histSize];
    
     unsigned int tmp = 0;
     for(unsigned int row=0; row < inputImg.GetLENGTH(); row++){
      for(int i=0; i<(inputImg.GetWIDTH()); i++){
       tmp = inputImg.GetBufferValue(i+row*2*(inputImg.GetWIDTH()));
       histBuffer[tmp] = histBuffer[tmp] + 1;
      }
     }
    }
    

    benutze ich ja ein übergebene IMAGE Könnte dadurch eine Indirektion vllt doch zustande kommen? Oder geht es dabei wirklich nur um den #include -Befehl?



  • Ah, sry, habe gemerkt, dass mein letzter Beitrag Blödsinn war 🙄



  • Xx_Mephisto_xX schrieb:

    SCHIRSCHADENDUDEL springt nun mitten aus meiner classIMAGE hervor 😉

    g++ -Wall main.cpp image.cpp hist.cpp -ltiff -o ausgabe
    In file included from main.cpp:5:0:
    image.h:83:1: Fehler: »SCHIRSCHADENDUDEL« bezeichnet keinen Typ
    image.cpp:405:20: Fehler: keine Elementfunktion »void IMAGE::invert()« in Klasse »IMAGE« deklariert
    image.cpp:406:18: Fehler: keine Elementfunktion »void IMAGE::test()« in Klasse »IMAGE« deklariert
    In file included from hist.h:4:0,
                     from hist.cpp:1:
    image.h:83:1: Fehler: »SCHIRSCHADENDUDEL« bezeichnet keinen Typ
    make: *** [all] Fehler 1
    

    Nun steh' ich hier ich armer Tor...

    Hab's gerade mit den beiden Files, so, wie Du sie eingestellt hast versucht.
    Klappt!

    furblewurble@sinsemilla /tmp $ cat test.cc
    #include "image.h"
    
    int main(){
      IMAGE i;
      i.invert();
    }
    furblewurble@sinsemilla /tmp $ g++ -pedantic -Wall image.cc test.cc -o test -ltiff
    image.cc: In member function ‘void IMAGE::ReadIMAGEDATA() const’:
    image.cc:138:67: warning: format ‘%i’ expects argument of type ‘int’, but argument 4 has type ‘tsize_t {aka long int}’ [-Wformat]
    image.cc: In member function ‘void IMAGE::grauwertStreckung(IMAGE&)’:
    image.cc:310:14: warning: long, short, signed or unsigned used invalidly for ‘Min’ [-pedantic]
    furblewurble@sinsemilla /tmp $
    

    Das ist ja doof. 🙂
    Vielleicht ein Backslash am Ende der Zeile vor invert() in image.h, der das Zeilenende unterdrückt? *phantasiert fröhlich*


Anmelden zum Antworten