Forum: PC-Programmierung C++ "Rückgabewert" vom Konstruktor


von Mr. T (Gast)


Lesenswert?

Hallo zusammen,

ist es möglich unter C++ vom Konstruktor einen Rückgabewert zu bekommen?
Man kann bei beim Instanziieren ja Argumente an den Konstruktor 
übergeben, warum also nicht auch einen Pointer und so mittels Call by 
Reference einen Rückgabewert "durch die Hintertür" erreichen?

viele Grüße!

: Verschoben durch User
von Peter II (Gast)


Lesenswert?

Mr. T schrieb:
> ist es möglich unter C++ vom Konstruktor einen Rückgabewert zu bekommen?

wie soll denn die Verwendung dann aussehen?

von Cyblord -. (cyblord)


Lesenswert?

Natürlich kann man einen Pointer übergeben und der Konstruktor schreibt 
da was rein. Und dann? Das ist aber kein Rückgabewert.
Dass es pfuschig und unübersichtlich (weil gänzlich unerwartet) ist, 
muss ich wohl gar nicht erst erwähnen.

von Karl H. (kbuchegg)


Lesenswert?

Mr. T schrieb:
> Hallo zusammen,
>
> ist es möglich unter C++ vom Konstruktor einen Rückgabewert zu bekommen?
> Man kann bei beim Instanziieren ja Argumente an den Konstruktor
> übergeben, warum also nicht auch einen Pointer und so mittels Call by
> Reference einen Rückgabewert "durch die Hintertür" erreichen?

Nichts und niemand hindert dich daran, das zu tun. Wie sinnvoll es ist, 
musst du entscheiden. Dem Compiler ist das egal, solange du dich im 
Rahmen der Sprachregeln bewegst.

Aber einen Returnwert, so wie bei normalen Funktionen, gibt es bei einem 
Konstruktor nicht.

: Bearbeitet durch User
von Klaus W. (mfgkw)


Lesenswert?

Manchmal ist es halt nötig (z.B. wenn man keine Exceptions nehmen kann, 
und im ctor etwas schief gehen kann).

Eine Alternative zu einem übergebenen Pointer oder Referenz zur 
Rückmeldung wäre noch ein interner Status, der je nach Erfolg des ctor 
gesetzt wird (evtl. auch von anderen Methoden später) und mit einer 
getStatus() o.ä. abgefragt werden kann.

PS: das hat dann eine gewisse Ählichkeit zu errno, nur halt ein Exemplar 
pro Objekt.

: Bearbeitet durch User
von Peter II (Gast)


Lesenswert?

Klaus Wachtler schrieb:
> Manchmal ist es halt nötig (z.B. wenn man keine Exceptions nehmen kann,
> und im ctor etwas schief gehen kann).

schon klar, aber wie sollte man es dann aufrufen?


Cx x(param)

wie würde man dann jetzt den Returnwert abfragen wollen?

von Klaus W. (mfgkw)


Lesenswert?

halt hinterher (vorher geht  ja nicht :-)
1
class Cx
2
{
3
public:
4
5
    enum eStatus
6
    {
7
        eStatusOk,
8
        eStatusOioioi,
9
        ...
10
    };
11
12
    eStatus getStatus()
13
    {
14
        return status;
15
    }
16
17
    Cx()
18
       : status(eStatusOioioi)
19
    {
20
        ... initiiaze something ...
21
        if( ichhabemigraene ) return;
22
        status = eStatusOk;´
23
    }
24
25
private:
26
    eStatus   status;
27
};
28
29
   Cx x(param);
30
   if( x.getStatus()!=Cx::eStatusOk ) ...

von Cyblord -. (cyblord)


Lesenswert?

Peter II schrieb:
> Klaus Wachtler schrieb:
>> Manchmal ist es halt nötig (z.B. wenn man keine Exceptions nehmen kann,
>> und im ctor etwas schief gehen kann).
>
> schon klar, aber wie sollte man es dann aufrufen?
>
>
> Cx x(param)
>
> wie würde man dann jetzt den Returnwert abfragen wollen?

Peter, oben beschreibt doch der TE dass er es über einen Pointer lösen 
will. Natürlich hat ein Konstruktor keinen Rückgabewert.

von Peter II (Gast)


Lesenswert?

cyblord ---- schrieb:
> Peter, oben beschreibt doch der TE dass er es über einen Pointer lösen
> will.
nein, er will es nicht über den Umweg Parameter lösen

von Cyblord -. (cyblord)


Lesenswert?

Peter II schrieb:
> cyblord ---- schrieb:
>> Peter, oben beschreibt doch der TE dass er es über einen Pointer lösen
>> will.
> nein, er will es nicht über den Umweg Parameter lösen

Er schreibt aber genau das hier:

> Man kann bei beim Instanziieren ja Argumente an den Konstruktor
> übergeben, warum also nicht auch einen Pointer und so mittels Call by
> Reference einen Rückgabewert "durch die Hintertür" erreichen?

von Oliver S. (oliverso)


Lesenswert?

Karl Heinz schrieb:
> Nichts und niemand hindert dich daran, das zu tun. Wie sinnvoll es ist,
> musst du entscheiden. Dem Compiler ist das egal, solange du dich im
> Rahmen der Sprachregeln bewegst.

Dem ist doch nichts weiter hinzuzufügen.

Oliver

von Amateur (Gast)


Lesenswert?

In vielerlei Hinsicht ist ein Konstruktor eine ganz einfache Funktion. 
Natürlich kannst Du der auch einen Zeiger oder eine Adressreferenz 
mitgeben.

Mir stellt sich dabei aber die einfache Frage: Was soll's?

Was hindert Dich daran das Ergebnis in der Klasse zu speichern und über:
Klassenreferenz.Rueckgabewert zu ermitteln?

von Bastler (Gast)


Lesenswert?

Wobei der Compiler auch einfach mal einen Default- und/oder 
Copy-Konstruktor bei Bedarf selbst anlegt. Diese arbeiten dann ohne 
"Fehlerausgang".

von Oliver S. (oliverso)


Lesenswert?

Bastler schrieb:
> Wobei der Compiler auch einfach mal einen Default- und/oder
> Copy-Konstruktor bei Bedarf selbst anlegt.

Nur, wenn er darf. Wenn nicht, dann nicht...

Oliver

von Dr. Sommer (Gast)


Lesenswert?

Alternative: Eine "optional" Klasse verwenden (wie zB Boost.Optional, 
kann man sich auch leicht selber bauen) und eine Factory-Funktion:
1
class MyClass;
2
3
// Factory-Funktion
4
inline optional<MyClass> createMyClass (int a, int b, int c);
5
6
class MyClass {
7
  friend optional<MyClass> createMyClass (int a, int b, int c);
8
  public:
9
    void doSomething ();
10
  private:
11
    // Konstruktor private, und Factory-Funktion ist "friend"; somit können nur über die Factory-Funktion Instanzen erstellt werden.
12
    MyClass (int a, int b, int c);
13
};
14
15
inline optional<MyClass> createMyClass (int a, int b, int c) {
16
  // Parameter gültig?
17
  if (a < 42 && b < c)
18
    // Instanz erstellen und zurückgeben
19
    return optional<MyClass> ( MyClass { a, b, c });
20
  // Parameter ungültig => Nichts zurückgeben
21
  return;
22
}
23
24
int main () {
25
  // Factory aufrufen zum Instanz erstellen...
26
  auto x = createMyClass ();
27
  // Instanz erstellt?
28
  if (x)
29
    x->doSomething ();
30
  else
31
    std::cout << "Fehler beim Anlegen der Instanz von MyClass.\n";
32
}
So spart man sich hässliche Dinge wie Output-Parameter und zusätzliche 
Member in der Klasse (Speicher-Verbrauch).

von Vlad T. (vlad_tepesch)


Lesenswert?

Dr. Sommer schrieb:
> Alternative: Eine "optional" Klasse verwenden (wie zB Boost.Optional,
> kann man sich auch leicht selber bauen) und eine Factory-Funktion:

schöner wäre eine imho eine statische Memberfunktion. Da entfällt auch 
die leidliche friend-Deklaration.
1
class MyClass {
2
  public:
3
    void doSomething ();
4
5
    static optional<MyClass> create(int a, int b, int c) 
6
    {
7
      // Parameter gültig?
8
      if (a < 42 && b < c){
9
        // Instanz erstellen und zurückgeben
10
        return optional<MyClass> ( MyClass { a, b, c });
11
      }
12
      // Parameter ungültig => Nichts zurückgeben
13
      return;
14
    }
15
16
  private:
17
    // Konstruktor privat; somit können nur über die Factory-Funktion Instanzen erstellt werden.
18
    MyClass (int a, int b, int c);
19
};
20
21
int main () {
22
  // Factory aufrufen zum Instanz erstellen...
23
  auto x = MyClass::create (1,2,3);
24
  // Instanz erstellt?
25
  if (x)
26
    x->doSomething ();
27
  else
28
    std::cout << "Fehler beim Anlegen der Instanz von MyClass.\n";
29
}

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Vlad Tepesch schrieb:
> schöner wäre eine imho eine statische Memberfunktion.
Ob schöner ist Ansichtssache. Die Factory-Funktionen in der Standard 
Library sind auch keine Member-Funktionen (std::make_shared zB).

von (prx) A. K. (prx)


Lesenswert?

Dr. Sommer schrieb:
> Alternative: Eine "optional" Klasse verwenden

Wie verbreitet ist das? Eine Doku sagt: "After reviewing national body 
comments to N3690, this library component was voted out from C++14 
working paper into a separate Technical Specification. It is not a part 
of the draft C++14 as of n3797."

von Dr. Sommer (Gast)


Lesenswert?

A. K. schrieb:
> Wie verbreitet ist das? Eine Doku sagt: "After reviewing national body
> comments to N3690, this library component was voted out from C++14
> working paper into a separate Technical Specification.
Ja, total bescheuert. Boost.Optional kann man aber immer 
nachinstallieren oder es eben selber implementieren.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.