überschriebene Methode aufrufen



  • Hallo,

    ich habe 2 Klassen (Basis und abgeleitete). ich erstelle ein Objekt der abgeleiteten Klasse und rufe eine Methode (OpenFromFile) auf, welche nur in der Basisklasse existiert. diese wiederrum ruft eine Methode (AddString) auf, welche von der Ableitung überschrieben wurde. Da das objekt vom Typ der Ableitung ist, sollte doch auch der Aufruf von der Ableitung ausgeführt werden, oder?

    Mein Code (Ausschnitt):

    class FileVector 
    
    {
    
      private:
    
        vector<string> v;
    
      protected:
    
        virtual void BuildVectorForSave(){};
    
      public:
    
        FileVector() {};
    
        virtual ~FileVector() {};
    
        void Clear() {v.clear();};
    
        virtual void AddString(string s)
        {
          g_print("FileVector::AddString %s\n",s.c_str());
          v.push_back(s);
        }
    
        void LoadFromFile(const char* filename)
    
        {
    
          ifstream f;  // Datei-Handle
    
          string line;
    
          Clear();
    
          if ((access(filename,04)!=-1))//check if file exists
    
          {
    
            f.open(filename, ios::in); // Öffne Datei
    
            if (f)
    
            {
    
              while (!f.eof())
    
              {
    
                getline(f, line); // Lese eine Zeile
    
                AddString(line);
    
              }
    
            }
    
          }
    
        }
    
        void SaveToFile(const char* filename)
    
        {
    
          //ofstream vectorFile(fileName, ios::out);
    
          BuildVectorForSave(); //generate Vector for derived classes (like map-based)
    
          ofstream vectorFile;
    
          vectorFile.open(filename);
    
          std::vector<string>::iterator i;
    
          for (i = v.begin(); i < v.end(); ++i) 
    
          {
    
            vectorFile << *i;
    
            vectorFile << endl;
    
          }
    
          vectorFile.close();
    
        }
    
    };
    
    class ConfigFile:public FileVector
    
    {
    
      private:
    
        map<string, string> table;
    
      protected:
    
        virtual void BuildVectorForSave()
    
        {
    
          FileVector::Clear();
    
          //iterate through map and add to vector
    
          std::map<std::string, std::string>::iterator iter;
    
          for (iter = table.begin(); iter != table.end(); iter++) 
    
          {
    
            {
    
              string s=iter->first+"="+iter->second;
              g_print("ConfigFile::BuildVectorForSave(): %s\n",s.c_str());
    
              FileVector::AddString(s);
    
            }
    
          }
    
        };
    
      public:
    
        ConfigFile() {};
    
        virtual ~ConfigFile() {};
    
        //virtual void AddString(string s,bool ignore_comments=true)
    
        virtual void AddString(string s)
        {
    
          g_print("ConfigFile::AddString %s\n",s.c_str());
          string key;
    
          string value;
    
          if (/*(!ignore_comments) ||*/ (s[0]!='#'))
    
          {
    
            unsigned int p=s.rfind("=");
    
            if ((p>=0) && (p!=string::npos))
    
            {
    
              key=s.substr(0,p);
    
              value=s.substr(p+1,s.length()-p);
    
              SetValue(key,value);
    
            }
    
          }
    
        }
    
        string GetValue(string key) {btrim(key);return table[key];}
    
        void SetValue(string key,string value) {btrim(key);btrim(value); table[key]=value;}
    
    };
    
    ConfigFile Last_Viewed;
    Last_Viewed.LoadFromFile(ms_lv.c_str());
    
    Last_Viewed.SetValue(file,GetTimeString()); //mehrere Felder in Configfile setzen
    
    Last_Viewed.SaveToFile(ms_lv.c_str());
    

    der effekt ist, dass am anfang nur der Vector geladen wird (obwohl AddString von ConfigFile aufgerufen werden sollte über FileVector:LoadFromFile).

    mit dem BuildVectorForSave() funktioniert es ja auch (ist ja eigentlich das gleiche Prinzip)...ich bekomme auch keine Fehlermeldung veim Compilieren.

    Sieht jemand meinen Fehler?

    Gruß Frank



  • frank schrieb:

    ich habe 2 Klassen (Basis und abgeleitete). ich erstelle ein Objekt der abgeleiteten Klasse und rufe eine Methode (OpenFromFile) auf, welche nur in der Basisklasse existiert. diese wiederrum ruft eine Methode (AddString) auf, welche von der Ableitung überschrieben wurde. Da das objekt vom Typ der Ableitung ist, sollte doch auch der Aufruf von der Ableitung ausgeführt werden, oder?

    Das ist richtig.

    Mein Code (Ausschnitt)

    184 Zeilen sind mir ehrlich gesagt zu viel. Wenn du das Problem auf das Wesentliche reduzierst, dann schau ich mir das gerne nochmal an.



  • In BuildVectorForSave rufst du explizit die Funktion (AddString) der Basisklasse auf, während in LoadFromFile die abgeleitete Version von AddString aufgerufen wird. Vielleicht ist das schon dein Problem.



  • HighLigerBiMBam schrieb:

    ... während in LoadFromFile die abgeleitete Version von AddString aufgerufen wird.

    Mein Problem ist, dass genau dass nicht pasiert...LoadfromFile ruft die AddString von der Basisklasse auf...

    so mal bisschen gekürzt der Code...fehlen halt jetzt die details,wo evtl. auch fehler stecken können...

    class FileVector
    {
      private:
        vector<string> v;
      protected:
        virtual void BuildVectorForSave(){};
      public:
        FileVector() {};
        virtual ~FileVector() {};
        virtual void AddString(string s)
        {
          g_print("FileVector::AddString %s\n",s.c_str());
          v.push_back(s);
        }
    
        void LoadFromFile(const char* filename)
        {
          ifstream f;  // Datei-Handle
          string line;
          Clear();
          if ((access(filename,04)!=-1))//check if file exists
          {
            f.open(filename, ios::in); // Öffne Datei
            if (f)
            {
              while (!f.eof())
              {
                getline(f, line); // Lese eine Zeile
                AddString(line);
              }
            }
          }
        }
    };
    
    class ConfigFile:public FileVector
    {
      private:
        map<string, string> table;
      public:
        ConfigFile() {};
        virtual ~ConfigFile() {};
        virtual void AddString(string s)
        {
          g_print("ConfigFile::AddString %s\n",s.c_str());
          ...
        }
        void SetValue(string key,string value) {btrim(key);btrim(value); table[key]=value;}
    
    };
    

    wenn ich LoadFromFile aufrufe wird der Text "FileVector::AddString..." ausgegeben, also wird die falsche Methode aufgerufen...es sollte ein Text á la "ConfigFile::AddString..." kommen. es geht also primär um Zeile 29.

    Gruß Frank



  • Es muss die abgeleitete Version aufgerufen werden, wenn die Klasse vom Typ abgeleitet ist! Ich sehe bei dir momentan keinen Fehler. Ich reduziere mal deinen Code auf ein Minimalbeispiel. Wenn du es damit schaffst den Fehler zu reproduzieren werden wir ihn finden 😕

    #include <iostream>
    
    class B
    {
    public:
    	void foo(){foobar();}
    	virtual void foobar(){std::cout << "Base\n";}
    };
    
    class D : public B
    {
    public:
    	virtual void foobar(){std::cout << "Derived\n";}
    };
    
    int main ()
    {
    	B base;
    	D derived;
    	B *b(&derived);
    
    	base.foo(); //Base!
    	derived.foo(); //Derived!
    	b->foo(); //Derived!
    
    	return 0;
    }
    


  • nach einigen Probieren geht es nun...
    keine Ahnung, was verkehrt war,

    danke trotzdem für die Hilfe


Anmelden zum Antworten