Globale Makros ?



  • 🙂 böse....ok.
    Also ich wollte eigentlich nur einen Return-wert definieren über ein makro.
    Also für die Lesbarkeit. und das wollte ich global machen. Also wenn in einer funktion return SUCCESS steht ist das ja schon mal hilfreicher als return 0 oder sonst ein int-wert.

    oder sollte ich diesbezüglich keine globale variante verwenden und statt dessen doch 0 oder 1 hinschreiben?

    Danke



  • Für lesbare Rückgabewerte stehen doch schon genug Bezeichnungen zur Verfügung - versuch's zum Beispiel mal mit 'true' und 'false' 😉

    (ansonsten reicht es doch sicher aus, die möglichen Fehlerwerte in dem Header zu definieren, in dem deine Funktion untergebracht ist - aber selbst dann würde ich eher einen enum verwenden als Makros)



  • testo schrieb:

    oder sollte ich diesbezüglich keine globale variante verwenden und statt dessen doch 0 oder 1 hinschreiben?

    Also, prinzipiell definiert man dafür globale Konstanten (*Konstanten*! Nicht Macros!). Aber wie CStoll schon sagte: für Wahrheitswerte gibt's den Datetyp 'bool' mit den konstanten Werten 'true' und 'false' und für Rückgabewerte ist all dies in den meisten Fällen ungeeignet, wenn etwas nicht klappt, wirft man lieber ne Ausnahme, anstatt den Rückgabewert dafür zu missbrauchen.



  • hmm....
    also wenn z.b folgendes nicht klappt:

    if ( !( f=fopen(file,"r") ) )
    	{
    		std::cout << 
    		"\n\tERROR: Could not open file \"%s\" for read access!\n" 
    		<< file << std::endl;
    		return READ_FAILURE;
    	}
    

    soll man da wirklich nen try block drum rum machen? Außerdem brauche ihc ja fürs catch auch ein return irgendwas oder?

    DIe main verwendet ja auch int als rückgabewert....

    wie ist es denn sauber wenn man mehrere fehlerquellen hat die in einer funktion ein return erzweingen z.B
    a) datei lesen
    b) berechnung
    c) datei schreiben

    sollte man dann für a, b und c wirklich nur einen return false ausgeben falls es zum fehler kommt?

    wie istes üblich ?

    Danke



  • testo schrieb:

    hmm....
    also wenn z.b folgendes nicht klappt:

    // ...
    

    soll man da wirklich nen try block drum rum machen? Außerdem brauche ihc ja fürs catch auch ein return irgendwas oder?

    Du sollst kein try darum machen, sondern statt der Ausgabe eine Exception werfen.

    if ( !( f=fopen(file,"r") ) )
        throw std::runtime_error (std::string ("Datei ") + file + " ist putt");
    

    testo schrieb:

    DIe main verwendet ja auch int als rückgabewert....

    Weil C das so macht und weil die Kommandozeile diesen Rückgabewert verarbeiten kann, Exceptions dagegen nicht.

    testo schrieb:

    wie ist es denn sauber wenn man mehrere fehlerquellen hat die in einer funktion ein return erzweingen z.B
    a) datei lesen
    b) berechnung
    c) datei schreiben

    sollte man dann für a, b und c wirklich nur einen return false ausgeben falls es zum fehler kommt?

    Nein, das sollte einfach nicht alles eine Funktion sein. Wenn jede Operation eine eigene Funktion ist, dann kannst du differenzierter auf die Exceptions eingehen.



  • #include <fstream>
    #include <iostream>
    #include <stdexcept>
    
    void show_file(const std::string& filename)
    {
        std::ifstream fs(filename.c_str(), std::ios::in);
        if (!fs)
            throw std::runtime_error("Could not open file");
    
        std::cout << fs.rdbuf() << std::endl;
    }
    
    int main()
    {
        try
        {
            show_file("test.txt");
        } catch(std::runtime_error& ex)
        {
            std::cout << "Datei: \"test.txt\" => " << ex.what() << std::endl;
        }
    }
    

    ...



  • Danke...mir wird einiges klarer...

    leider habe ich in Bezug auf die Exceptions jetzt eine Frage:

    Wie würde man z.B folgendes realisieren:

    int main(...)
    {
         Class1 cl;
         cl.funktion1();
    }
    
    //hier in der klasse Class1
    Class1::funktion1()
    {
         try
        {
            show_file("test.txt");
        } catch(std::runtime_error& ex)
        {
            std::cout << "Datei: \"test.txt\" => " << ex.what() << std::endl;
        }
    
        //wenn weitere funktionen aus dieser funktion aufgerufen werden die
        //wiederum zum abbruch führen sollten....
        //wie mache ich das??? Wird dann wirlich immer ein try-catch block um jeden
        //funktionsaufruf gemacht? wäre doch sehr unübersichtlich. 
    
       //Und wie würde ich jetzt der main mitteilen dass etwas schief gelaufen ist? 
      //ich kann ja nicht sowas machen oder?:
       try
        {
            show_file("test.txt");
        } catch(std::runtime_error& ex)
        {
            throw std::runtime_error("Error ist aufgetreten");
            std::cout << "Datei: \"test.txt\" => " << ex.what() << std::endl;
        }
    }
    


  • Wie wäre es mit sowas?

    int main(...)
    {
         Class1 cl;
         try {
             cl.funktion1();
         }
         catch(std::runtime_error& ex)
         {
             std::cout << "Datei: \"test.txt\" => " << ex.what() << std::endl;
         }
    }
    
    //hier in der klasse Class1
    Class1::funktion1()
    {
        show_file("test.txt");
        show_file("test.txt"); //Wenn bei einer der beiden aufrufe eine Exception geworfen wird, wird sie in dem catch-block von main() aufgefangen.
    }
    


  • globale konstanten sind genauso böse wie makros. sind doch hier nicht in c :p



  • thordk schrieb:

    globale konstanten sind genauso böse wie makros.

    Ach Quatsch. Wenn Konstanten global angesprochen werden, was spricht dann dagegen, sie global (natürlich über nen Namensbereich) zugängig zu machen?

    Kapseln in Klassen macht man vielleicht in Java, weil es dort eben nicht anders geht. Aber denselben Sinn (nämlich der Zuordnung in einen eigenen Namensbereich) erhält man in C++ eben auch über Namensbereiche und Kompiliereinheiten bzw. Include-Dateien). Das ist ein sauberes, modulares Vorgehen.



  • ok danke...ich hab jetzt in der main sowas:

    wäre das unsauber ....das bad_alloc habe ich da falls irgendwo intern mal eine alloziierung nicht klappen sollte....

    wie beende ich eigentlich meine main....ist das ok so über den EXIT_FAILURE?
    Oder ist das abort() gängig?

    try {
                .....
               //hier ikommen noch paar funktionsaufrufe
               ......
    	         try
    		{
    			fkt(...);
    		}
    		catch (std::runtime_error& ex) 
    		{
    			std::cout << ex.what() << std::endl;
    			return EXIT_FAILURE;
    		}
         catch (std::bad_alloc &e) 
          {
    		std::cerr << "\n\tPROGRAM ABORTED: " 
    				  << e.what() << "\n\t\t  ERROR: Not enough memory.\n"           >< std::endl;
    		std::cerr << "\t===========================================\n" << std::endl;
    		abort();
          }
    

Anmelden zum Antworten