[Spiel] Findet die Fehler ...



    1. er wollte erreichen, dass eine exception in der objektinitialisierungsliste gecatcht wird (aus dem vom vorposter genannten grund).
    2. die exception wird so oder so weitergeschmissen, da nicht garantiert werden kann, dass das Objekt in validem Zustand ist.
    3. z.B. das ganze in den Body des Konstruktors verlagern.


  • Alternativ kann man auch ein C-String mit fester Länge benutzen und so den Code ausnahmefrei bekommen.

    Folgender Code produziert 1 Fehler bei der Übersetzung. Bitte keinen Compiler benutzen, da die Fehlermeldungen in der Regel recht eindeutig sein sollte.

    #include <vector>
    #include <algorithm>
    using namespace std;
    
    namespace foo{
    	struct Data{
    		int a;
    	};
    
    	bool operator<(const Data&a, const Data&b){
    		return a.a < b.a;
    	}
    
    	void swap(Data&a, Data&b){
    		if(&a != &b){
    			a.a ^= b.a;
    			b.a ^= a.a;
    			a.a ^= b.a;
    		}
    	}
    }
    
    class MyContainer:private vector<foo::Data>{
    	typedef vector<foo::Data> super;
    public:
    	using super::iterator;
    	using super::const_iterator;
    	using super::begin;
    	using super::end;
    	using super::size;
    	using super::empty;
    };
    
    class MySuperContainer:public MyContainer{
    public:
    	void fast_sort(){
    		if(size() == 2){
    			iterator i = begin(), j = i;
    			++j;
    			if(*j < *i)
    				swap(*j, *i);
    		}else
    			sort(begin(), end());
    	}
    };
    


  • hmm, das einzige, was mir aufgefallen ist, ist, dass swap eigentlich im namespace foo ist, oder?
    naja, ich werds jetzt mal durchn compiler laufen lassen 😛

    Spoiler:

    edit: es lässt sich tatsächlich durch Ändern zu foo::swap(... lösen.
    was ich allerdings ursprünglich nicht gewusst (nur etwas geahnt) hatte, ist, dass vector auch eine methode swap besitzt (*referenz-nachguck*). Aber da diese Methode dazu da ist, die Inhalte eines vectors mit denen eines anderen zu tauschen, ist die hier wohl nicht sondelich hilfreich.



  • Heinzelotto schrieb:

    hmm, das einzige, was mir aufgefallen ist, ist, dass swap eigentlich im namespace foo ist, oder?

    Dank Koenig-Lookup dürfen solche Helferfunktionen auch im gleichen Namesraum wie der Typ selbst sein.



  • Ben04 schrieb:

    Heinzelotto schrieb:

    hmm, das einzige, was mir aufgefallen ist, ist, dass swap eigentlich im namespace foo ist, oder?

    Dank Koenig-Lookup dürfen solche Helferfunktionen auch im gleichen Namesraum wie der Typ selbst sein.

    Spoiler:

    ok, dann ergibt das Sinn. Der Compiler denkt, dass der User die methode vector::swap aufrufen will, die ja aber durch die private vererbung unzugänglich geworden ist (und die sowieso nicht von den übergabeparametern her passt). Durch absolute Qualifizierung der anderen Methode lässt sich das Problem aber umgehen.



  • Wie wird es geheilt?

    class MySuperContainer:public MyContainer{
    public:
        void fast_sort(){
            using ::std::swap; // <---
            if(size() == 2){
                iterator i = begin(), j = i;
                ++j;
                if(*j < *i)
                    swap(*j, *i);
            }else
                sort(begin(), end());
        }
    };
    


  • #include <iostream>
    #include <vector>
    #include <string>
    
    struct bar
    {
       int id;
       std::string name;
    };
    
    bar* find(std::vector<bar*> const &vec, std::string const &theName)
    {
       for(std::vector<bar*>::const_iterator it = vec.begin(); it != vec.end(); ++it)
       {
          if((*it)->name == theName)
          {
              return *it;
          }
       }
       return 0;
    }
    
    bool exists(std::vector<bar*> const &vec, std::string const &theName)
    {
       return find != 0;
    }
    
    void print(std::vector<bar*> const &vec)
    {
       for(std::vector<bar*>::const_iterator it = vec.begin(); it != vec.end(); ++it)
       {
          std::cout << (*it)->name << ", " << (*it)->id << std::endl;
       }
    }
    

    Der Code kompiliert, tut aber nicht das, was er eigentlich soll. So wie es hier ist, dürfte es reicht einfach zu finden sein...

    Felix



  • Klassiker.



  • die adresse von find, die ja != 0 ist, ergibt immer "wahr"



  • Schnell was kurzes:

    //dat1.cpp
    extern int S;
    extern int var = 112;
    
    int main()
    {
        int zahl = S * var;
    }
    
    //dat2.cpp
    int var;
    const int S = 10;
    

    Beide werden natürlich gegeneinander gelinkt.



  • Was wollte der Programmierer und was ist falsch?

    #include <iostream>
    
    class friends{
    public:
    	friends(int i):n(i){}
    	bool operator^(friends const & o){return n<o.n;}
    	void operator~(){n++;}
    	bool operator%(friends mo){	
    		int s=0;int i = 1;
    		for(;i < mo.n;i++){
    			switch(mo.n%i){
    				default: continue;
    				case 1: s+=i;
    			}
    		}
    		return s==n;
    	}
    	friend std::ostream& operator << (std::ostream& os, friends const& s){
    		return os<<s.n;
    	}
    
    private:
    	int n;
    };
    
    int main(int argc, char *argv[])
    {
    	for(friends i = 1; i^20000; ~i){
    		friends j = 1;
    		switch(j^i){
    			for(; j^i; ~j){
    				default:
    				if(!(j^i && i^j) && i%j && j%i) std::cout << j << "  " << i << std::endl;
    				continue;
    			}
    			case 0:
    				break;
    		}
    	}
    }
    


  • KasF schrieb:

    //dat1.cpp
    extern int S;
    extern int var = 112;
    
    int main()
    {
        int zahl = S * var;
    }
    
    //dat2.cpp
    int var;
    const int S = 10;
    

    1. Fehler: Mehrfache Definition von var, da die eine direkte initialisierung bei extern auch gleichzeitig eine Definition ist, wohingegen ohne = x nur eine Deklaration.

    2. Fehler: Globale const Variablen sind wie globale static's, dh lokal innerhalb der Übersetzungseinheit. Deswegen führt ein extern int S zu einem 'undefined reference'. Abhilfe: Noch ein extern vor der Definition.

    Nun habe ich wieder Akku-Power und heute Abend kommen dann wieder schöne Codes.



  • class LittleDataClass 
    {
       friend class MyClass;
    
       private:
                LittleDataClass() { };
    };
    
    class MyClass 
    {
        private:
                 LittleDataClass dclass;
    };
    

    1.) Was wollte der Programmierer hier erreichen ?
    2.) Hätte er es besser machen können ?

    typedef unsigned int uInt;
    
    class LetterCounter
    {
    	virtual uInt getCounts(char c) = 0;
    };
    
    class LetterCounter1 : public LetterCounter
    {
        private:
                 string str;
        public:
                 explicit LetterCounter1(const string& str) : str(str) { }
    
                 uInt getCounts(char c) 
                 {
                     uInt helper = 0;
                     for(size_t i = 0; i < str.size(); ++i)
                                     if( c == str[i] ) ++helper;
    
                     return helper;
                 }
    
    };
    
    class LetterCounter2 : public LetterCounter
    {
        private:
                 map<char, uInt> county;	
        public:
                 explicit LetterCounter2(const string& str) 
                 {
                    for(size_t i = 0; i < str.size(); ++i) 
                            ++county[str[i]];
                 }
    
                 uInt getCounts(char c) 
                 {
                     return county[c];
                 }
    
    };
    
    void showAllCounts(const LetterCounter& lc, const string& str)
    {
    	for(size_t i = 0; i < str.size(); ++i) 
    	{
    		cout << "Count of ." << str[i] << ". in <" << str << ">: " << lc.getCounts(str[i]) << endl; 
    	}
    }
    
    int main()
    {
    	string str1 = "das ist doch alles voll easy";
    	string str2 = "kommt denn nichtmal was schwieriges";
    
    	LetterCounter1 lc1(str1);
    	LetterCounter2 lc2(str2);
    
    	showAllCounts(lc1, str2);	
    	cout << "Count of .a. in str1: " << lc2.getCounts('a') << endl; 
    
    }
    

    1.) Wo ist hier das Problem ?
    2.) Hätte der Programmierer getCounts() nicht besser mit const versehen sollen?



    1. Vermutlich soll LittleDataClass nur von MyClass instantiiert werden dürfen 2) eine sinnvollere Lösung als die Friend-Geschichte wäre vermutlich, LittleDataClass zur privaten Unterklasse von MyClass zu machen.

    3)Das Problem ist, dass der output von showAllCounts(lc1, str2); behauptet, die Anzahl der jeweiligen Zeichen in str2 auszugeben - tatsächlich wird getcounts aber die Anzahl der Zeichen des Strings ausgeben, mit dem der Counter initalisiert wurde, also str1.

    1. getCounts hätte mit const versehen werden sollen, damit der Aufruf in showAllCounts legal ist und überhaupt kompiliert. Allerdings hätte dann LetterCounter2::getCounts mit konstanten map-methoden umgeschrieben werden müssen:
    uInt getCounts(char c) const
    {
      map<char, uInt>::const_iterator pos = county.find(c);
      if (pos == conty.end() ) return 0;
      else return pos->second;
    }
    

    einen const_cast auf die map loszulassen oder sie als mutable zu deklarieren wäre unschön bzw. ein Designfehler.

    1. Andererseits könnte man LetterCounter1::getCounts vereinfachen:
    uInt getCounts(char c) const
    {
      return std::count(str.begin(), str.end(), c);
    }
    

    Die Aufgaben sind was nettes zum Frühstück 😉



  • All right 🙂

    Weiter gehts:
    showAllCounts(lc1, str2); wird nun zu showAllCounts(lc1, str1);

    3.) Was hat der Programmierer sich mit zwei funktional gleichen Klassen erhofft ?
    4.) Hat der Programmierer seinen Plan aus 3. erfüllt ?
    5.) Wieso ist std::map nicht so schlau und liefert ein Proxy, um so zwischen Lesen und Schreiben zu unterscheiden und um so den Overhead bei const-Methoden zu vemeiden?



    1. weil der standard es nicht erlaubt
    2. unterschiedliche implementierung für unterschiedliche anforderungen, kurz: optimierung
    3. ja, die frage ist nur ob sein plan überhaupt sinnvoll war


  • dieses programm:

    int main()
    {
      // was muss hier rein? 
    }
    

    soll in C wie auch in C++ compilierbar sein, aber sich in C anders verhalten als in C++.
    besondere schikane: nur eine zeile und die zeile darf nicht länger als, na sagen wir mal 30 zeichen sein (ausgenommen white spaces).
    wem fällt was ein?
    🙂



  • -fricky- schrieb:

    dieses programm:

    int main()
    {
      // was muss hier rein? 
    }
    

    soll in C wie auch in C++ compilierbar sein, aber sich in C anders verhalten als in C++.
    besondere schikane: nur eine zeile und die zeile darf nicht länger als, na sagen wir mal 30 zeichen sein (ausgenommen white spaces).
    wem fällt was ein?
    🙂

    int main()
    {
      struct s {char c;}; int s; int i = sizeof('6') + sizeof(s); //na, was kommt raus?
    }
    

    Okay, sind ca. 50 Zeichen plus whitespaces, aber dafür 2 Features die in C udn C++ verschieden sind 😛



  • int main()
    {
      volatile int v;int i=v=0;
    }
    


  • -fricky- schrieb:

    dieses programm...

    int main()
    {
      return sizeof('x');
    }
    

Anmelden zum Antworten