# Hilfe bei C++ Programm (ungelöst)



## Crymes (21. Januar 2012)

*Hilfe bei C++ Programm (ungelöst)*

Hallo,
Ich bin gerade dabei, ein Zahlenrate-Spiel von mir sauberer, strukturierter zu Schreiben.
Früher stand in meiner Main nur ein Funktionsaufruf, mit dem ich dann per return(Funktionsname) zur nächsten funktion gesprungen bin usw. .
Jetzt habe ich alles komplett neu geschrieben. (Auch ein paar Features geändert)
In der Main stehen die Funktionen (bis jetzt 3) und in den Funktionen ist dann der Code geschrieben, ich benutze aus Unfähigkeit nur globale Variablen zur Übergabe.
MEin Problem: Wenn ich in die Funktion kein return reinschreibe (Was auch?), öffnet und schließt sich das Programm als wenn nichts drin stehen würde.
Wenn ich die Funktionen mit void definiere kommt folgendes:
int stringumwandlung(void)': Überladene Funktion unterscheidet sich nur hinsichtlich des Rückgabetyps von 'void stringumwandlung(void).
Könnt ihr mir helfen?


----------



## AMD (21. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Wäre es auch möglich Code zu posten? Das würde sicherlich helfen.


----------



## Crymes (21. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

So, der Code ist im Anhang. Bin über Hilfe sehr dankbar 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## AMD (21. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Sollte nun Funktionieren (zumindest tut es das bei mir) 

Dein Hauptproblem war, dass du vor einem Funktionsaufruf z.B. int geschrieben hast! Eine Funktion ruft man aber nicht mit einem Datentyp wie z.B. int auf.
Falsch:

```
int Zahlen()
```
Richtig:

```
Zahlen()
```
Habe außerdem noch paar Kleinigkeiten am Syntax verbessert sowie einen Fehler behoben in der Funktion "schwierigkeitsbestimmung()"
Wenn dort ein anderer Buchstabe angegeben wurde, dann blieb der Schwierigkeitsgrad bei 0! => Das Programm stürzt in den nachfolgenden Operationen ab. Habe daher einen Default-Wert festgelegt.

Falls noch was ist einfach melden 

Edit// Code-Update:
- Die Globale Variable "abstand" von 0 auf 100 gesetzt. Verhindert Absturz bei einer Falscheingabe.



			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## Crymes (21. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Also erstmal danke, bei mir funktioniert deine Version, musste nur noch diesen komischen header stdafx.h hinzufügen.
Das einzigste, eas du am Code geändert hattest war doch der default abstand, oder? Sonst fallen mir keine Unterschiede auf.
Wenn ich diese Zeile bei mir per Copy and Paste einfüge, funktioniert es trotzdem nicht.
Kannst du mir die anderen Stellen noch zeigen, ich übersehe die irgendwie immer.


----------



## AMD (21. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Okay, gleich als Beispiel die main()


```
int main()
{
    int schwierigkeitsbestimmung();
    int hauptspiel();
    
}
```

Du schreibst vor deinen Funktionsaufrufen "int" - das gehört da aber nicht hin sondern nur der Funktionsname!
Bei void hauptspiel() das gleiche:

```
int stringumwandlung();
```

Verstanden?^^


----------



## Crymes (22. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ja, ich habs mir beim einschlafen gedacht, dass dort der Fehler sein muss.
Weißt du, wie man ?,ä,ü,ö usw. in der Konsole anzeigen kann?


----------



## AMD (22. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Dü müsstest dann beim cout gleich den Ascii Code angeben und das noch als char casten!
ä = cout << (char)132 << endl;
ü = cout << (char)129<< endl;
ö = cout << (char)148 << endl;


----------



## Crymes (22. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ich glaub ich definiere mir am anfang die ascis als ae, ss usw. . Dann brauch ich beim schreiben nur den string anzugeben. Finds aber irgendwie blöd, dass das noch nicht genormnt ist.


----------



## AMD (22. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Oder so.
Aber ich glaube an der "Normung" wird sich erstmal nix ändern


----------



## hardware_fanatiker (22. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

das hier sollte auch funktionieren : Highscore - Die Boost C++ Bibliotheken - String-Verarbeitung

Auch sei nochmal angemerkt, das linux das ja von haus aus kann.


----------



## Crymes (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

So hab jetzt ein fettes Problem: Ich rufe ja eineig Funktionen in der Main auf, bis ich zu einer Funkltion komme, an der gefragt wird, ob man vielleicht nochmal spielen möchte oder den Schwierigkeitsgrad ändern möchte etc. .
Wenn man da was auswählt (ich springe aus der Funktion mit retourn in eine andere) läuft das Programm noch einm einziges mal durch, bevor es sich beendet. Ich glaube, es liegt daran, dass die main funktion dann zu Ende ist und den Pointer (heist das so?) nicht wieder an den Anfang setzt. 

Kennt jemand abhiolfe ohne den kompletten code umzukrempeln??

Anbe der Quellcode:


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## AMD (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Spring doch einfach neu zur main, dann ist die auch nicht zuende


----------



## Crymes (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Aber wenn ich direkt das spiel noch einmal spielen will?
Gibts da keine möglichkeit?


----------



## bingo88 (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ein paar grundsätzliche Dinge vorab:

Standard-Includes, die vom System/Compiler bereitgestellt werden, solltest du mittels *#include <header>* (bspw. #include <string> oder #include <stdio.h> - also mit den spitzen Klammern) einbinden.

Wenn du eine Funktion schon mit Rückgabetyp definierst, solltest du auch was zurückgeben - wenn du nichts zurückgibst, nimmt der halt irgendetwas und das ist immer Käse.

```
[B]int[/B] main()
{
    // ...
    [B]return 0;[/B] // oder ein anderer Statuscode

    // ...
}
```
Code der Form

```
[B]void[/B] caller()
{
    // ...
    return myFunction(); // Prototyp: [B]void[/B] myFunction();

    // return <Wert>; macht bei einer void Funktion an sich schon wenig Sinn.
}
```
ist auch verwirrend, da myFunction nichts zurück gibt, ergo das Statement was anderes macht, als es dem Leser suggerieren mag. Abgesehen davon ruft man mit return keine Funktion auf, sondern verlässt sie (und gibt ggf. einen Wert zurück -> bei non-void Funktionen). Auch wenn es eine Zeile mehr code ist, würde ich das aus Lesbarkeitsgründen so schreiben (ich habe das ehrlich gesagt bei void Funktionen auch noch nicht anders gesehen):

```
void caller()
{
    // ...
    myFunction(); // Funktion aufrufen
    return; // caller verlassen

    // ...
}
```
Zumal du dir bei solchen Abfragen das return eh sparen kannst:

```
void caller()
{
    if (condition == A)
    {
        callA();
    }
    else if (condition == B)
    {
        callB();
    }
    else
    {
        callDefault();
    }
}
```
Sinnvoll wäre ein return hier z. B.:

```
void theFunc()
{
    int testvalue = doMagicCalc();

    if (testvalue == TV_A)
    {
         // mach was
         handleA();
         return; // Funktion theFunc() vorzeitig verlassen
    }

    // alle anderen Fälle (bei sowas kurzem könnte man auch ein else nutzen und das obige return einfach weglassen)
    everythingElse();
}
```
Nun zu deiner eigentlichen Frage:

```
// includes spar ich mir mal...

int main()
{
    bool bExit = false;

    while (!bExit)
    {
        bExit = abfrage(); // alles andere wird in der Funktion geregelt
    }

    return 0;
}

bool abfrage() // Achtung: Deklaration auch auf bool statt void ändern!
{
    // wenn die Funktion true zurück gibt, wird beendet (s. o.)
    string wahl="";

    cout << endl << "W" << ae << "hlen sie bitte zwischen folgenden Optionen:" << endl << endl; 
    cout << "noch einmal Spielen:            n" << endl << "In Punkteliste einschreiben:    e" << endl << "Punkteliste ansehen:            a" << endl << "Schwierigkeitsgrad neu w" << ae << "hlen:  s" << endl;
    cout << "Beenden: x" << endl; // neu
    cin >> wahl;
    
    if (wahl == "n")
    {
        hauptspiel();
        return false; // nicht beenden
    }
    else if (wahl == "e")
    {
        speichern();
        return false; // nicht beenden
    }
    else if (wahl == "a")
    {
        liste();
        return false; // nicht beenden
    }

    else if (wahl == "s")
    {
        schwierigkeitsbestimmung();
        return false; // nicht beenden
    }
    else if (wahl == "x")
    {
        return true; // beenden
    }
    else
    {
        cout << fehler << endl << endl;
        return abfrage(); // hier wird abfrage rekursiv aufgerufen!!!
    }
}
```
Du solltest evtl. noch sinnvolle Standardwerte (z. B. für die Schwierigkeit) eintragen, da man in dem Beispiel jetzt die Schwirigkeitsabfrage einfach überspringen kann. Ich habe den Code jetzt so aus dem Kopf runtergesemmelt, daher ist das nicht getestet. Müsste aber als grobe Richtung erst mal helfen


----------



## Crymes (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Jetzt hab ich mal ne blöde frage: Du hast boolexit doch auf false gesetzt, die while schleife wird dann ausgeführt, wenn der bool true ist.
Aber das ist er doch gar nicht?????


----------



## Crymes (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ich habe das jetzt so programmiert, dass er, wenn die funktion zum ersten mal ausgeführt wird als erstes schwierigkeit, dann hauptspiel aufruft. Nur wird ab einem gewissen Zeitpunkt nur noch schwierigkeitsbestimmung aufgerufen.

Falls ihr noch geduld mit mir habt: Hier ist der Code 


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## bingo88 (23. Januar 2012)

*AW: Problem mit den Funktionen bei C++*



Crymes schrieb:


> Jetzt hab ich mal ne blöde frage: Du hast boolexit doch auf false gesetzt, die while schleife wird dann ausgeführt, wenn der bool true ist.
> Aber das ist er doch gar nicht?????


 Der Operator ! negiert den Wert (NOT-Operator):

```
bool bExit = false;
if (!bExit)
{
    // !(false) ergibt true und !(true) ergibt false
}
```
Ich werde zu deinem Code mal was ausführlicheres schreiben und dann den Code hochladen, dass wird mir hier sonst als Post zu unübersichtlich. Ich nehme jetzt mal an, du lernst momentan C++. Auf wie viel Wissen kann ich denn zurückgreifen? Davon hängt nämlich ab, wie ausführlich ich das erklären muss, ich möchte ja schließlich, dass du dabei was lernst und nicht wie der Ochs vorm Berg stehst 

Update: Ich habe dir jetzt mal ein paar Kommentare in deinen Code geschrieben, siehe Anhang. Wenn du absolut nicht mehr weiter weißt, ich habe auch eine funktionierende und recht saubere Lösung hier. Sag dann einfach Bescheid und ich lade die auch hoch.


----------



## Crymes (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

1. Das eigentliche Problem meiner letzten Frage war also, dass ich nur = anstatt == geschrieben habe.....da wär ich nich draufgekommen, ich dachte das wäre nur bei strings nötig.

2. Ich werde jetzt mal probieren das Programm entsprechend deiner Tipps umzuschreiben, da arbeite ich mich noch mal in die Rückgabewerte von Funktionen ein, habe mich bisher immer davor gedrückt.

3. Danach habe ich vor noch ne Punkteliste zu Implmentieren , so vielleicht mit vergleichsdatei oder verschlüsselung, damit niemend einfach einen Wert in der Liste ändert (eigentlich nur zur Übung und zum Spaß an der Freude)

4.Danach - das wo ich immer gescheitert bin - das gante in eine clr Anwendung zu übertragen .

Werde jetzt mit dem Überarbeiten erstmal etwas länger brauchen, da noch ein paar Arbeiten anstehen, ich meld mich aber dann wieder.

Bis hierhin schonmal vieln Dank !


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*



Crymes schrieb:


> 4.Danach - das wo ich immer gescheitert bin - das gante in eine clr Anwendung zu übertragen .


Willst du daraus eine .NET Anwendung machen (auch Konsole)?


----------



## Crymes (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

ja, eine .net (c++) mit Buttens, list boxen usw....


----------



## Skysnake (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Warum machste das nicht in C++? Ich schätze mal, du nutzt Visual Studio. Da ist doch alles drin, um das in C/C++ zu machen. Läuft dann zwar nur unter windows, aber das haste mit .net auch (fast)


Was mich allerdings wundert ist, was bingo88 da schreibt zu den funktionen.

Wenn er schreibt

void funktionsname(){

//ich mach etwas

return irgendwas;
}

Dann darf das gar nicht funktionieren, da die Funktion ja als void Funktion geklariert ist, also ohne Rückgabewert. Eigentlich sollte das eine Fehlermeldung geben.

Genau wies einen Compilererror gibt, wenn man die Fuktion nicht void macht, sondern z.B. int und dann etwas anderszurück gibt als einen int, oder gar nichts zurück gibt.

Genau so siehts doch auch mit den Parametern aus.

Er lässt das ja z.B. frei, also

void meineFunktion();

Wenn man aber 

void meineFunktion(void);

schreibt, dann darf man gar keinen Parameter übergeben, sonst gibt es einen compiler error.

Zumindest sollte das so sein, wenn ich jetzt nicht total aufm Holzweg bin.

Ich finde, du solltest dir die Sache mit Deklaration und Implementierung von Funktionen nochmals durchlesen. Insbesondere, wenn ich da an Headerfiles denke. Das sind wirklich basics. Die sollten sitzen.


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

@Skysnake Ich meinte das Richtige, habe es aber nicht klar formuliert. Das sollte eigentlich so heißen: "*return <wert> hat bei void Funktionen nichts zu suchen!*". Ich bezog mich an der fraglichen Stelle darauf, dass die aufgerufene Funktion myFunction an sich void ist und daher keinen Rückgabewert liefert. Etwas untergegangen ist dabei allerdings die Tatsache, dass caller() auch void ist und somit ebenfalls nichts zurückgeben kann. Das wollte ich eigentlich mit dem Kommentar "_// return <Wert>; macht bei einer void Funktion an sich schon wenig Sinn._" ausdrücken, ist aber wohl was misslich. Der ganze Codeblock ist als so-soll-man-es-nicht-machen zu verstehen, ich hätte das wohl deutlicher kennzeichnen sollen.

Parameter an eine Funktion zu übergeben, die nicht in der Deklaration auftauchen, liefert zumindest in VS nen Linker-Error. Fehlende/falsche Rückgabewerte liefern entweder auch nen Error oder nur ne Warning, da bin ich mir jetzt grade nicht mehr sicher...


----------



## Skysnake (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ich weiß doch, das du weißt, was geht und was nicht.  Es war halt in meinen Augen nur nicht klar für Crymes.

Ich glaub der gcc wirft da keinen Fehler, bin mir aber ganz ehrlich da auch nicht 100% sicher. Man kann so halt auf jeden Fall klar zwischen überladenen Funktionen unterscheiden, wenn man das void dazu nimmt.

Ich finds halt sauberer, wenn man Funktionen ohne Parameter das void als Parameter mit gibt


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*



Skysnake schrieb:


> Es war halt in meinen Augen nur nicht klar für Crymes.


Da hast du Recht! Hab ich ja jetzt auch geschrieben, war was ungeschickt formuliert ^^



Skysnake schrieb:


> Ich  glaub der gcc wirft da keinen Fehler, bin mir aber ganz ehrlich da auch  nicht 100% sicher. Man kann so halt auf jeden Fall klar zwischen  überladenen Funktionen unterscheiden, wenn man das void dazu nimmt.
> 
> Ich finds halt sauberer, wenn man Funktionen ohne Parameter das void als Parameter mit gibt


 Da ist was dran. Ich glaub der VS Klassenassistent macht das auch so (wenn man ihn denn nutzen möchte). Der macht aber auch nen paar andere Sachen:

```
class Blubb
{
public:
    Blubb(void);
    ~Blubb(void);

private:
    int m_var1;
    int m_var2;
    int m_var3;
};

// Vom VS Klassenassistenten generierte Initialsierungsliste
Blubb::Blubb(void)
: m_var1(0)
, m_var2(0)
, m_var3(0)
{
}
```
Das ist zwar jetzt ziemlich OT, aber ich bin da gestern drüber gestolpert und ich finde diese Formatierung der Initialisierungsliste irgendwie sehr unnatürlich...


----------



## Skysnake (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

ähm...

Ich glaub da bist du jetzt auf nen ziemlichen Sonderfall gestoßen, der VIEL mehr macht, als du dir gerade Denkst 

Das erste Blubb ist ja für die Klasse, sozusagen wie das std halt ein Namespace

Das zweite Blubb ist dann der Funktionsname der Klasse blubb mit dem Parametern (void), also keinen, die du übergibst.

Das : m_var1(0) sollte dann sein, dass du etwas überlädst, was als Klassenvariable definiert ist. Zumindest heißt dass das :

(EDIT: (0) ist der Wert, mit dem du die vorher deklarierte Variable initialisierst. Das ist ja der Konstruktor für das Objekt der Klasse Blubb. Also nicht wirklich überladen, sondern eben der Wert mit dem die Variable initialisiert wird.)

Du hast in dem Fall halt die "m_var" in einem Headerfile definiert.

Ich seh so Code im Moment mehr oder weniger jeden Tag 

Mal ein "kleines" Beispiel:


```
/*
 * Copyright (c) 2002-2005 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ron Dreslinski
 *          Ali Saidi
 */

/**
 * @file
 * Declaration of a bus object.
 */

#ifndef __MEM_BUS_HH__
#define __MEM_BUS_HH__

#include <list>
#include <set>
#include <string>

#include "base/hashmap.hh"
#include "base/range.hh"
#include "base/range_map.hh"
#include "base/types.hh"
#include "mem/mem_object.hh"
#include "mem/packet.hh"
#include "mem/port.hh"
#include "mem/request.hh"
#include "params/Bus.hh"
#include "sim/eventq.hh"

class Bus : public MemObject
{
    /** Declaration of the buses port type, one will be instantiated for each
        of the interfaces connecting to the bus. */
    class BusPort : public Port
    {
        bool _onRetryList;

        /** A pointer to the bus to which this port belongs. */
        Bus *bus;

        /** A id to keep track of the intercafe ID this port is connected to. */
        int id;

      public:

        /** Constructor for the BusPort.*/
        BusPort(const std::string &_name, Bus *_bus, int _id)
            : Port(_name, _bus), _onRetryList(false), bus(_bus), id(_id)
        { }

        bool onRetryList()
        { return _onRetryList; }

        void onRetryList(bool newVal)
        { _onRetryList = newVal; }

        int getId() { return id; }

      protected:

        /** When reciving a timing request from the peer port (at id),
            pass it to the bus. */
        virtual bool recvTiming(PacketPtr pkt)
        { pkt->setSrc(id); return bus->recvTiming(pkt); }

        /** When reciving a Atomic requestfrom the peer port (at id),
            pass it to the bus. */
        virtual Tick recvAtomic(PacketPtr pkt)
        { pkt->setSrc(id); return bus->recvAtomic(pkt); }

        /** When reciving a Functional requestfrom the peer port (at id),
            pass it to the bus. */
        virtual void recvFunctional(PacketPtr pkt)
        { pkt->setSrc(id); bus->recvFunctional(pkt); }

        /** When reciving a status changefrom the peer port (at id),
            pass it to the bus. */
        virtual void recvStatusChange(Status status)
        { bus->recvStatusChange(status, id); }

        /** When reciving a retry from the peer port (at id),
            pass it to the bus. */
        virtual void recvRetry()
        { bus->recvRetry(id); }

        // This should return all the 'owned' addresses that are
        // downstream from this bus, yes?  That is, the union of all
        // the 'owned' address ranges of all the other interfaces on
        // this bus...
        virtual void getDeviceAddressRanges(AddrRangeList &resp,
                                            bool &snoop)
        { bus->addressRanges(resp, snoop, id); }

        // Ask the bus to ask everyone on the bus what their block size is and
        // take the max of it. This might need to be changed a bit if we ever
        // support multiple block sizes.
        virtual unsigned deviceBlockSize() const
        { return bus->findBlockSize(id); }

    };

    class BusFreeEvent : public Event
    {
        Bus * bus;

      public:
        BusFreeEvent(Bus * _bus);
        void process();
        const char *description() const;
    };

    /** a globally unique id for this bus. */
 [B][COLOR=red]   int busId;
    /** the clock speed for the bus */
    int clock;
    /** cycles of overhead per transaction */
    int headerCycles;
    /** the width of the bus in bytes */
    int width;[/B]
    /** the next tick at which the bus will be idle */
    Tick tickNextIdle;

    Event * drainEvent;

usw....
```


```
/*
 * Copyright (c) 2006 The Regents of The University of Michigan
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Ali Saidi
 */

/**
 * @file
 * Definition of a bus object.
 */

#include <algorithm>
#include <limits>

#include "base/misc.hh"
#include "base/trace.hh"
#include "debug/Bus.hh"
#include "debug/BusAddrRanges.hh"
#include "debug/MMU.hh"
#include "mem/bus.hh"

Bus::Bus(const BusParams *p)
    : MemObject(p),[B][COLOR=red] busId(p->bus_id), clock(p->clock),
      headerCycles(p->header_cycles), width(p->width)[/B], tickNextIdle(0),
      drainEvent(NULL), busIdle(this), inRetry(false), maxId(0),
      defaultPort(NULL), funcPort(NULL), funcPortId(-4),
      useDefaultRange(p->use_default_range), defaultBlockSize(p->block_size),
      cachedBlockSize(0), cachedBlockSizeValid(false)
{
    //width, clock period, and header cycles must be positive
    if (width <= 0)
        fatal("Bus width must be positive\n");
    if (clock <= 0)
        fatal("Bus clock period must be positive\n");
    if (headerCycles <= 0)
        fatal("Number of header cycles must be positive\n");
    clearBusCache();
    clearPortCache();
}

usw...
```
Den wichtigen Teil hab ich mal Rot gemacht. Wie du siehst wird das durchaus verwendet. Ich muss aber auch sagen, ich bin da 100% noch nicht durch gestiegen, wie das alles jetzt zu verstehen ist, wobei ich auch sagen muss, ich hab noch das Problem, das ich gemischten C/C++&Python Code habe  Da wirds dann SEHR interessant, den Code zu verstehen bei, was warens?, 250.000-500.000 Zeilen Code


----------



## AMD (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Nochmal zum void + return;
Dieses Post bezieht sich auf Skysnake's Aussage:


> Dann darf das gar nicht funktionieren, da die Funktion ja als void  Funktion geklariert ist, also ohne Rückgabewert. Eigentlich sollte das  eine Fehlermeldung geben.
> 
> Genau wies einen Compilererror gibt, wenn man die Fuktion nicht void  macht, sondern z.B. int und dann etwas anderszurück gibt als einen int,  oder gar nichts zurück gibt.



Das klappt theoretisch schon! Bingo88 hatte ja bei dem Code keinen Interger, Float oder sonst was zurückgegeben sondern eben eine Funktion, daher läuft das auch ohne Error.
Schließlich gibt int eine Zahl zurück und bei void kommt eben eine void zurück. Dass das natürlich wenig Sinn macht ist die andere Sache.
Visual wird da vermutlich rummeckern von wegen Rekursiv bla aber vom Syntax her ist da kein Fehler drin.


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ich meinte hier schon die Initialisierungsliste (sprich m_varX ist Member der Klasse Blubb und keine globale Var). Ich mache aus Gewohnheit viel mit der IL, daher ist mir der Krempel recht gut vertraut. Mir ging es eigentlich um die _Formatierung_ (aber danke für die ausführliche Erklärung ). Ich hätte es halt eher so formatiert:

```
Blubb::Blubb(void) :
    m_var1(0),
    m_var2(0),
    m_var3(0)
{
}
```
Aber Visual Studios Autoformat macht dann komische Sachen damit 

Edit: Hab mal meinen Code von vorher ergänzt, sodass es nun klarer sein sollte.


----------



## Crymes (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Zur frage weiter vorn: Ich wollte das in ferner Zeit in VS mit c++ und .net schreiben


----------



## Skysnake (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Naja, schau dir mal meinen Code an, das ist auch nicht besser formatiert. 

PS: Was ist jetzt der Unterschied zwischen nem Member und ner globalen Variable?  Jetzt ernst gemeint. Ich weiß auch nicht jedes Detail, und hatte vorher damit recht wenig zu tun.

Verhält sich doch ähnlich, nur das eben wenn ich ne echte globale Variable habe über die Objektinstanzen diese als const deklarieren müsste, was ja in meinem Code meistens der Fall ist. Und bei Member kanns halt auch nur einfach innerhalb des Objekts was "globales" sein. Oder überseh ich da was?

Sorry fürs highchecken des Threads


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Irgendwie habe ich deinen Code falsch gedeutet, das "globally unique" im Kommentar über einer der Variablen zusammen mit den verschachtelten Klassen hat mich verwirrt. Da gibt es keine globale Variable, *das war totaler Quatsch von mir*! Die von dir markierten Stellen (int busId, etc.) sind normale public Membervariablen der Klasse Bus. Mit einer Initialisierungsliste kann man ja eh nur auf Member einer Klasse zugreifen, wie komme ich bloß auf so einen Müll  Naja, jedenfalls ist das ein typisches Beispiel für die Verwendung einer Initialisierungsliste.

@Crymes: Ich könnte dir für grafische Oberflächen auch Qt empfehlen, das ist "normales" C++ und du kannst denselben Code auch für Linux nutzen. Ich persönlich finde das einfacher als C++/CLR.


----------



## Skysnake (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*

Ja, ich hab Qt auch schon verwendet. Das geht ganz gut, aber ist teilweie ziemlich hartet Tobak. Ich empfehle dir auf jeden Fall die Entwicklungstools dazu zu verwenden!!!

Und ich hoffe du lässt Multithread Programmierung dazu weg. 

Ich habs mit MPI, OpenMP und PThreads kombinieren dürfen, und teils war das echt ugly.

bingo88:
Das mit der "globalen" Variable hab ich gesagt, weil ich das Konstrukt vorher noch nie gesehen hatte, aber so interpretiert hatte. Aber gut zu wissen, dass die Dinger Membervariablen heißen.

Meine Erklärung bzgl der Zugriffe etc. hat doch aber gestimmt oder? Halt nur den richtigen Namen nicht gekannt.

Kannste eventuell noch was dazu sagen, warum man das mit variablen_name(irgendwas) macht, und was das bedeutet?

Wäre echt nett, weil der Code funktioniert, ich kann ihn erweitern etc. haber wäre schon gut zu wissen, dass das auch wirklich alles so passt. Auf das Konstrukt trifft man eben normal nicht. -.-


----------



## bingo88 (24. Januar 2012)

*AW: Problem mit den Funktionen bei C++*



Skysnake schrieb:


> Kannste eventuell noch was dazu sagen, warum man das mit variablen_name(irgendwas) macht, und was das bedeutet?


 Natürlich.

Nehmen wir mal wieder unsere Klasse Blubb:

```
class Blubb
{
public:
    Blubb(void);
    ~Blubb(void);

private:
    int m_var1;
};
```
Du hast bei dieser Klasse zwei Möglichkeiten deine Membervariable m_var1 zu initialisieren (Membervariable heißt einfach nur, dass sie an eine Instanz der Klasse gebunden ist; gibt ja noch globale und statische Variablen):

```
// "Klassisch" im Konstruktor
Blubb::Blubb(void)
{
    m_var1 = 0;
}
```


```
// Initialisierungsliste
Blubb::Blubb(void) :
m_var1(0)
{
}
```
Die beiden Varianten sind hier vollkommen äquivalent.

Anders sieht das hier aus:

```
class Blubb
{
public:
    Blubb(void);
    ~Blubb(void);

private:
    const int m_var1; // die ist nun const!
};
```
Das Initialisieren im Konstruktor klappt jetzt nicht mehr, da der Body vom Konstruktor aufgerufen wird, nachdem die Variablen initialisiert wurden! (Klingt was komisch, hängt aber mit den internen Abläufen bei C++ zusammen; siehe ganz unten).

```
Blubb::Blubb(void)
{
    m_var1 = 0; // oops, m_var1 ist const :(
}
```
Hier musst du jetzt die Initialisierungsliste verwenden, da diese vor dem eigentlichen Konstruktor durchlaufen wird:

```
Blubb::Blubb(void) :
m_var1(0)
{
    // so ist das ok, m_var1 hat jetzt den Wert 0
}
```
Richtig spannend wird das aber eigentlich erst, wenn du komplexe Datentypen (andere Klassen) als const-Membervariablen hast.

```
class A
{
public:
    A(int param) :
        m_param(param)
    {
        // hier ginge auch m_param = param!
    }

    ~A(void)
    {
    }

private:
    int m_param; // nicht const
};

class B
{
public:
    B(void) :
       m_a(1337) // hier wird der Konstruktor von A mit param = 1337 aufgerufen
    {
        // m_a(1337) geht nicht, da m_a const ist!
    }

    ~B(void)
    {
    }

private:
    const A m_a; // const
};
```
Bei dem letzten Beispiel kommt noch hinzu, dass die Klasse A keinen parameterlosen Standardkonstruktor besitzt, daher müsstest du hier mittels der Initialisierungsliste den Konstruktor von A so oder so aufrufen.

Die Syntax ist identisch mit dem Aufruf von Basisklassenkonstruktoren, da das Problem dahinter ähnlich ist.

Du kannst das also ruhig weiter verwenden, das ist kein Problem. Wie gesagt, bei konstanten Membervariablen oder fehlendem Standardkonstruktor hast du eh keine andere Wahl und musst das so machen.

Edit: Hier ein Beispiel, was ich mit den internen Abläufen meine.

```
class Blubb
{
public:
    Blubb(void);
    ~Blubb(void);

private:
    std::string m_text;
};


Blubb::Blubb(void)
{
    m_text = "Hallo, Welt!";
}
```
Was hier im Konstruktor Blubb::Blubb(void) passiert ist folgendes:
Zuerst wird ein leeres m_text Objekt erzeugt (also der Standardkonstruktor von std::string aufgerufen).
Standardkonstruktoren werden immer dann aufgerufen wenn a) kein Eintrag in der Initialisierungsliste vorhanden und b) ein Standardkonstruktor verfügbar ist.

Danach erfolgt eine Zuweisung des Texts "Hallo, Welt!" an m_text. Hier wird also zuerst ein Objekt angelegt und anschließend direkt wieder überschrieben. Bei Objekten, die eine komplexe und damit teure Initialisierung haben, ist das natürlich Gift für die Performance!

Anders sieht es hier aus:

```
Blubb::Blubb(void) :
m_text("Hallo, Welt!")
{
}
```
Hier wird direkt der Konstruktor von std::string mit dem Parameter "Hallo, Welt!" aufgerufen, was natürlich billiger ist.


----------



## Crymes (21. Februar 2012)

*AW: Problem mit den Funktionen bei C++*

Hab mich jetzt mal wieder mit dem Programm beschäftigt, scheiter aber nach wie vor wegen nicht gewollten beendens.
Kann mir einer nochmal sagen, was ioch jetzt mit dem bool und dem while falsch gemacht hab?

Es geht genauer um die funktionen main und abfrage.


			Dieser Inhalt steht nur eingeloggten Mitgliedern zur Verfügung.


----------



## Crymes (22. Februar 2012)

*AW: Hilfe bei C++ Programm*

Kann mir da noch jemand helfen?


----------

