Ausgabeparameter in C++ ohne Zeiger



  • Hiho,
    Ich hab ein wenig Erfahrung mit Turbo Pascal durch den Schulunterricht, hab aber angefangen C++ zu lernen.
    Wie bekomme ich Ausgabeparameter ohne diesen ganzen Zeigerkram hin?

    #include "stdafx.h"
    #include "iostream"
    #include "string"
    using namespace std;
    
    void Eingabe(string);
    
    int main()
    {
    	string s="";
    	Eingabe(s);
    	cout << "\nEs wurde " << s << " eingegeben!" << endl;
    	cin >> s;
    	return 0;
    }
    
    void Eingabe(string& s)
    {
    	cout << "Bitte geben sie eine Zeichenfolge ein: ";
    	cin >> s;
    }
    

    Wenn ich das jedoch so starte gibt mir Visual C++ eine für mich nicht verwertbare Fehlermeldung zurück:
    call by reference.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""void __cdecl Eingabe(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> >)" (?Eingabe@@YAXV?basic_string@DU?basic\_string@DU?char_traits@D@std@@V?$allocator@D@2@@std@@@Z)" in Funktion "_main".



  • Ändere

    void Eingabe(string);
    

    nach

    void Eingabe(string&);
    


  • Ahh Danke The-Kenny jetzt funzt alles 😃



  • Hmm ja guck dir mal in deinem Buch/Tutorial das Thema param-by-value | param-by-ref | param-by-ptr an ^^

    #include <iostream>
    #include <string>
    
    void input(std::string const&, std::string&);
    
    int main()
    {
        std::string string;
        input("Bitte geben Sie eine Zeichenfolge ein: ", string);
        std::cout << "\nSie gaben \"" << string << "\" ein!" << std::endl;
        std::cin.get();
    }
    
    void input(std::string const& prompt, std::string& dest);
    {
        std::cout << prompt << std::flush;
        std::getline(std::cin, dest);
    }
    

    🙂 so die Header heißen <string> (statt "string") und <iostream> (statt "iostream"). Dann gewöhn dir diesen using namespace-Kram gar nicht erst an 😃



  • using namespace ist schon ok, solange man nicht den fehler macht und es in den globalen scope eines headers schreibt.

    /* kann ins auge gehen */
    using namespace std;
    
    class Foo
    {
     void foo();
    };
    
    /* kann höchstens zu kollisionen im eigenen namespace führen */
    namespace MyNamespace
    {
      using namespace std;
    
      class Foo
      {
       void foo();
      };
    }
    
    /* eher unkritisch */
    Foo::foo()
    {
      using namespace std;
      // code
    }
    


  • (D)Evil schrieb:

    🙂 so die Header heißen <string> (statt "string") und <iostream> (statt "iostream")

    Sag das mal meinen Compiler 🙂 ( benutze Visual C++ )
    Wenn ich eine Klasse erzeuge, ich benutze jetzt mal das Bsp. aus meinem Buch.
    Header:

    #ifndef _KONTO_
    #define _KONTO_
    #include <iostream>
    #include <string>
    using namespace std;
    
    class Konto
    {
    	private:
    		string name;
    		unsigned int nr;
    		double stand;
    
    	public:
    		bool init(const string&, unsigned long, double);
    		void display();
    };
    #endif
    

    Die Funktionen

    #include <stdafx.h>
    #include <iomanip>
    #include <konto.h>
    using namespace std;
    
    bool Konto::init(const string& i_name, unsigned long i_nr, double i_stand)
    {
    	if ( i_name.size() < 1 )
    		return false;
    	name	= i_name;
    	nr		= i_nr;
    	stand	= i_stand;
    	return true;
    }
    
    void Konto::display()
    {
    	cout << fixed << setprecision(2)
    		 << "--------------------------------------\n"
    		 << "Kontoinhaber:  " << name  << "\n"
    		 << "Kontonummer:   " << nr    << "\n"
    		 << "Kontostand:    " << stand << "\n"
    		 << "--------------------------------------\n" 
    		 << endl;
    }
    

    Gibts die tolle Fehlermeldung:
    fatal error C1083: Datei (Include) kann nicht geöffnet werden: "konto.h": No such file or directory

    Dann muss das sicherlich irgendwo anders hin, nur wohin hab ich keine Ahnung.



  • Ja ... also Dateien die in deinem Verzeichnis sind, gibst du mit "..." an, Dateien die er aus seinen vordefinierten Pfaden finden soll, gibst du mit <...> an. (Um es vereinfacht zu sagen)

    #if !defined(KONTO_H__INCLUDED) // _XYZ gehört Compiler!
    #define KONTO_H__INCLUDED
    
    // #include <iostream> warum hier schon, wenn du es noch nicht brauchst?
    #include <string>
    // using namespace std; niemals im Header
    
    #if (_MSC_VER >= 1300)
    #pragma once
    #endif // (_MSC_VER >= 1300)
    
    class Konto
    {
    // private: default bei Klasse
        std::string m_name;
        unsigned int m_nummer;
        double m_guthaben;
    
    public:
        // bool init(const string&, unsigned long, double); In Konstruktor packen
        Konto(std::string const& name, unsigned int number, double balance) 
            : m_name(name), m_nummer(number), m_guthaben(balance) 
        {}
        // void display(); operator << überladen!
        friend std::ostream& operator <<(std::ostream& out, Konto const& data) 
        {
            out << "Konto " << data.m_nummer << "\n\tInhaber: " << data.m_name << "\n\tGuthaben: " << data.m_guthaben;
            return out;
        }
    };
    
    #endif // KONTO_H__INCLUDED
    

    Da wäre dann

    #include "konto.h"
    

    Wenn sich die Datei dann in einem Verzeichnis tiefer befindet

    #include ".\xyz\konto.h"
    

    ... usw ^^



  • Ok Danke.
    using namespace niemals im Header ok^^

    // bool init(const string&, unsigned long, double); In Konstruktor packen
    

    Konstruktor kommt erst nächstes Kapitel 😉

    Nur ab Zeile 24 versteh ich nix mehr.
    Was bedeutet das der Operator überladen ist? Und überhaupt: welcher Operator? Da steht doch nur der Funktionstyp und der Funktionsname.
    Zeile 25-28 sind dann nur noch kryptische Fragmente für mich.



  • friend std::ostream& operator <<(std::ostream& out, Konto const& data) 
        { 
            out << "Konto " << data.m_nummer << "\n\tInhaber: " << data.m_name << "\n\tGuthaben: " << data.m_guthaben; 
            return out; 
        }
    

    Bedeutet, dass der <<-Operator (Ausgabeoperator) überladen wurde.
    Damit ist es jetzt möglich, eine Instanz deiner Klasse in einen beliebigen Stream auszugeben (cout u.ä., fstream etc.)


Anmelden zum Antworten