Wie viele werte kann eine funktion maximal zurückgeben? C++

3 Antworten

Methoden geben einen oder keinen Wert zurück. Dies wurde willkürlich festgelegt und hat sich bisher bei allen Programmiersprachen bewährt.

Allerdings hast du recht; im Prinzip könnten Methoden ebenso wie sie mehrere Eingabewerte verarbeiten auch mehrere Ausgabewerte ermitteln. „Aber solltest du unrecht haben, tritt Absatz 1 in Kraft“ …

Manchmal geschieht dies „versteckt“. In C++ kann man ja Objekte und Strukturen definieren. Wenn nun ein solches Objekt erzeugt wird, kann man es über „seinen“ Zeiger erreichen. Dieser Zeiger übergibt damit quasi „mehrere“ Parameter. Vielleicht ist dies ein wesentlicher Grund, warum man immer nur maximal „einen“ Rückgabewert als Ergebnis abliefert. Der zweite wäre einfach, dass man damit signalisiert, ob die Methode ein brauchbares Ergebnis geliefert hat oder nicht.

PWolff  19.05.2015, 13:56

Dieses Vorgehen ist übrigens der Standard fast aller mit Windows mitgelieferten DLLs. Der Zeiger auf den eigentlich gewünschten Wert wird als Funktionsargument übergeben. Rückgabewert == 0 bei Fehlschlag, Rückgabewert != 0 bei Erfolg. Im Fehlerfall muss man GetLastDLLError() aufrufen, um erraten zu können, was diesmal schiefgegangen ist.

1
NoHumanBeing  19.05.2015, 19:48

Dies wurde willkürlich festgelegt und hat sich bisher bei allen Programmiersprachen bewährt.

Nein. Es gibt Sprachen, wo mehrere Rückgabewerte erlaubt sind. Go zum Beispiel.

package main

import (
"fmt"
"io/ioutil"
)

func main() {
var content []byte
var err error
content, err = ioutil.ReadFile(path)

if err != nil {
fmt.Printf("Error reading file: %s", path)
} else {
// Do something with them ...
_ = content
_ = err
}

}

Es gibt einige Sprachen, die das können. Ich meine mich zu erinnern, dass es in Python auch möglich ist.

0
wolfgang1956  20.05.2015, 06:31
@NoHumanBeing

Nein. Es gibt Sprachen, wo mehrere Rückgabewerte erlaubt sind. Go zum Beispiel.

Sieht man so in der Wikipedia. In den dortigen Beispielen findet sich nicht eines mit „mehreren“ Rückgabewerten. Das Gleiche gilt für Python.

Ich meine mich zu erinnern, dass es in Python auch möglich ist.

Erinnerungen können manchmal einfach nur falsch sein …

Zwar zweifle ich nicht grundsätzlich, aber ich bezweifle, dass deine „Beispiele“ wirklich zielführend sind. Man kann ihnen nicht einmal entnehmen, was der Rückgabewert sein soll bzw. was das System mit zwei unterschiedlichen Rückgabewerten anfangen soll, wenn ich die Unterstriche der beiden letzten „Zeilen“ als „Return-Ersatz“ interpretieren darf?

Während unter UNIXen, Linuxen, OS X und Windows irgendein Errorcode wie „err“ noch irgendwie interpretiert, untersucht und abgefangen werden kann, wüsste ich nicht, was ich im Beispiel mit „content“ machen sollte. Eine Variable wie „success“ könnte man da noch verstehen …

0

Also wenn man ganz semantisch sein will kann eine Funktion maximal einen Wert zurückgeben, jedoch gibt es ein paar "tricks" wie man dies umgehen kann. Wenn man eine Funktion haben will welche mehr als einen integralen datentypen zurück gibt und das jedes mal so kann man einfach ein struct erstellen welches die benötigten daten beinhaltet und dies dann zurückgeben. Hat man jedoch eine funktion welche entweder einen oder einen anderen, jedoch nicht beide gleichzeitig zurückgibt, so empfiehlt es sich ein union zu verwenden, da ein union in solchen Fällen speichereffizienter ist als ein struct da ein union immer nur maximal so viel speicher belegt wie sein größter member. Hat man jedoch eine Funktion welche alterierende Datentypen hat so kann man, entweder, falls man die boost bibliothek verwendet ein boost::any zurückgeben, oder falls man kein boost verwendet einen void *

//Beispiel 1
struct koordinaten {
//struct ist in C++ der klasse ähnlich mit dem unterschied das alle member standardmäßig public sind
//C++ unterstützt keine C-Style structs
koordinaten(int x, int y) : _x(x), _y(y) {}
int _x;
int _y;
};
koordinaten x(int x, int y){
koordinaten temp(x, y);
return temp;
}
//Beispiel 2
union my_return_type {
koordinaten k;
int hoehe;
};
my_return_type x(int x, int y, int h){
my_return_type temp;
if(x == 0 && y == 0){
temp.hoehe = h;
}else {
temp.k._x = x;
temp.k._y = y;
}
return temp;
}
//Beispiel 3
void *x(int x){
int a = 10;
double b = 3.14;
std::string c = "";
switch(x){
case 1:
return (void *)&a;
break;
case 2:
return (void *)&b;
break;
case 3:
return (void *)&c;
break;
}

Nur ein Rückgabewert.

Aber das kann natürlich durchaus ein komplexer Datentyp, wie ein Pointer oder ein struct sein.

Und Du kannst natürlich Pointer und/oder Referenzen in der Argumentliste haben, die Du innerhalb der Funktion auch "manipulieren" kannst und diese Änderungen werden dann (im Gegensatz zu "Wertetypen") "nach außen sichtbar".

PWolff  18.05.2015, 23:10

Soweit ich weiß kennt C++ noch explizite Zeiger, sodass die Unterscheidung zwischen "Referenztypen" und "Wertetypen" wie in C# hier gegenstandslos ist.

Die indirekte Rückgabe über Funktionsargumente nennt man auch "Nebenwirkungen". Sie sollten mit Bedacht eingesetzt werden, besonders in Funktionen mit Rückgabewert (also von einem anderen Typ als void), sonst kommt man schnell durcheinander.

1
PWolff  19.05.2015, 13:53
@NoHumanBeing

Inzwischen hab ich mich an Wert- und Refereztypen so ziemlich gewöhnt.

Aber wenn man einmal verstanden hat, wie ein Zeiger funktioniert, sehnt man sich immer wieder danach zurück, besonders, wenn ein Kollege in C# eine struct in eine class oder umgekehrt umdefiniert hat und man dann hübsche Warnungen über nicht initialisierte Variablen oder lustige NullReferenceExceptions (aka null pointer exceptions) kriegt ...

1
NoHumanBeing  19.05.2015, 19:40
@PWolff

Ich habe schon recht viel in C-Sharp programmiert, auch größere Projekte, und habe (bis auf Builtin-Types) noch NIE ein struct benötigt.

Ebenso habe ich noch keine "stackalloc"-Arrays benötigt.

0