Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Implizite Konvertierung mit Klammer-Operator ()

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
30.08.2006, 19:30 Uhr
Yadgar



High!

Ich versuche gerade, einen Klammeroperator für eine implizite Wandlung zwischen zwei Klassen zu programmieren:


C++:
struct B;

struct A
{
   int i;
   double d;
   operator B() const;
};

struct B
{
   B (void);   // Standardkonstruktor, initialisiert s mit Nullzeiger
   B (A&, int i); // Konstruktor, initialisiert B-Objekt mit A-Objekt
   string s;
};


A::operator B() const
{
   B b;
   cout << "Typwandlung per Operator!" << endl;
   char buf[32];
   sprintf(buf, "i: %i, d: %f", i, d);
   b.s = buf;
   return b;
}    

... (weiterer Code)

int main()
{
   A a1;
   a1.i = 1747;
   a1.d = 5.55552;
   B b3;
  
   b3(a1);
  
   getchar();
}



Wenn ich den "Aupperle" richtig verstanden habe, sollte b3(a1) das A-Objekt a1 entsprechend der Operatorfunktion nach B wandeln und b3 zuweisen... stattdessen bekomme ich eine von diesen Fehlermeldungen, mit denen ich so rein gar nichts anzufangen weiß: no match for call (B) (A&)... wieso steht das B hier in Klammern? Verwende ich den Operator falsch, müßte es irgendwie b3 = b3(a1) heißen?

Und überhaupt, müssen Compiler-Fehlermeldungen eigentlich so kryptisch sein. dass man den Eindruck bekommt, sie wären von Nerds für Nerds programmiert worden?

Bis bald im Khyberspace!

Yadgar
--
Flagmaker - ein Programmier-Blog

Dieser Post wurde am 30.08.2006 um 19:48 Uhr von FloSoft editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
30.08.2006, 20:33 Uhr
stephanw
localhorst



C++:
struct B;

struct A
{
   int i;
   double d;
   operator B() const;
};

struct B
{
   B (void);   // Standardkonstruktor, initialisiert s mit Nullzeiger
   B (A&, int i); // Konstruktor, initialisiert B-Objekt mit A-Objekt
   string s;
}


Damit kannst Du z.B. sowas hier schreiben:

C++:
void f()
{
  A a;
  B b1( a , 4711 );
  B b2 = a; // aus a ein B machen und zuweisen
  B b0( a ); // könnte auch klappen, wenn aus a erst mittels A::operator B() ein B gemahct wird und dann der (implizit vorhandene) CopyCon B::B(const B&) gerufen wird.
  // da bin ich mir grad nicht sicher, ob der Compiler so schlau ist bzw. ob der Standard das fordert (?)
  
  // dagegen
  B b3;
  b3(a1); // sucht nach B::operator()( A& ), was Dein Compi auch sagt ;-)

}



Tante Edit: insgesamt ist die implizite Konvertierung mit großer Vorsicht zu genießen, weil man dem Code häufig nicht mehr ansieht, was eigentlich passiert. Wenn man das braucht, ist häufig eine explizite Konvertierung mit einer Funktion A::toB() oder B::toA() besser, weil lesbarer und weniger fehleranfällig.
--
Reden ist Schweigen und Silber ist Gold.

Dieser Post wurde am 30.08.2006 um 20:38 Uhr von stephanw editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
30.08.2006, 21:08 Uhr
Yadgar



High!


Zitat von stephanw:

Tante Edit: insgesamt ist die implizite Konvertierung mit großer Vorsicht zu genießen, weil man dem Code häufig nicht mehr ansieht, was eigentlich passiert. Wenn man das braucht, ist häufig eine explizite Konvertierung mit einer Funktion A::toB() oder B::toA() besser, weil lesbarer und weniger fehleranfällig.


Mit anderen Worten, so lange es nicht darum geht, sich in fremdem Code zurecht zu finden, den mehr oder weniger Berufene verbockt haben, sondern selbst von Grund auf neu zu programmieren, handelt es sich um ein eher exotisches Randgebiet, mit dem sich näher zu beschäftigen eher Zeitverschwendung ist... oder wird tatsächlich öfters so verquast programmiert, dass man nicht mehr unterscheiden kann, was jetzt Funktion, Initialisierung in Funktionsschreibweise oder Wandlungsoperator ist?

Bis bald im Khyberspace!

Yadgar
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
30.08.2006, 21:18 Uhr
stephanw
localhorst


Jein, ganz so hart würde ich es nicht ausdrücken. Es ist in jedem Fall gut, zu wissen, was die Sprache alles kann und zulässt. Zeitverschwendung würde ich das nicht nennen, wenn Du Dich damit beschäftigst.

In realistischem Anwendungscode hatte ich bisher äußerst selten die Notwendigkeit für diese Operatoren. Aber man könnte damit z.B. Wrapper-Klassen für eingebaute numerische Typen machen, die sich wie eingebaute Typen verhalten:


C++:
class Integer
{
public:
  Integer( int i );
  operator int() const;
private:
  int i;
};

void g()
{
  int i = 5;
  Integer integer = 7;

  int k = i + integer;
}



Frage mich jetzt nicht nach dem Sinn einer solchen Klasse ;-) So wirklich fällt mir spontan keiner ein, mit etwas Überlegen vielleicht schon.
--
Reden ist Schweigen und Silber ist Gold.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
30.08.2006, 22:14 Uhr
Yadgar



High!


Zitat von stephanw:
Jein, ganz so hart würde ich es nicht ausdrücken. Es ist in jedem Fall gut, zu wissen, was die Sprache alles kann und zulässt. Zeitverschwendung würde ich das nicht nennen, wenn Du Dich damit beschäftigst.

[...]

Frage mich jetzt nicht nach dem Sinn einer solchen Klasse ;-) So wirklich fällt mir spontan keiner ein, mit etwas Überlegen vielleicht schon.


Das scheint wirklich alles etwas weit hergeholt... aber so langsam dämmert es mir, wie dieser Operator eingesetzt wird! Die Deklaration mit den Klammern verwirrt etwas, wenn man bisher vor allem die arithmetischen und Speicheranforderungsoperatoren kennt... in diesem Fall wäre es sozusagen eine implizite Umwandlung auf einen einfacheren Typ... gefährlich, sowas!

Bis bald im Khyberspace!

Yadgar
--
Flagmaker - ein Programmier-Blog
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
31.08.2006, 11:39 Uhr
Th



@stephanw: deine Klasse macht als Wrapper schon Sinn, nämlich wenn man den Konstruktor noch mit 'explicit' deklariert:

C++:
class Integer
{
public:
  explicit Integer( int i );
  operator int() const;
private:
  int i;
};



Nun verhält sich diese Klasse wie ein int (durch den cast-operator), aber das Erzeugen eines Integers muß explizit erfolgen, d.h. wenn eine Funktion einen Integer verlangt, dann muß man auch Integer(0) schreiben und nicht nur 0.

Allgemeiner kann man diese Klasse natürlich auch in ein template packen:

C++:
template<typename T>
class Wrapper
{
public:
  explicit  Wrapper( T t )
    : m_t(t)
  {}

  operator T() const { return m_t };

private:
  T m_t;
};



Nun kann man z.B. typedef Wrapper<int> Jahr schreiben. Dies ist besser als "typedef int Jahr", denn dann kann man nicht einfach eine andere beliebige Variable z.B. ein Tag oder Monatswert als Jahr übergeben, z.B. bei einer Funktion wie SetDate(int, int, int) weiß man nicht, welches nun Tag, Monat oder Jahr ist, aber bei SetDate(Jahr, Monat, Tag) ist dies dann eindeutig.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
31.08.2006, 13:33 Uhr
ao

(Operator)


Hier wäre noch ein Anwendungsfall:

C++:
#include <string>
#include <iostream>

class DayOfWeek
{
    static const char * m_dayNames [];

    int m_day;

public:

    DayOfWeek (int day)
    : m_day (day)
    {
    }

    operator std::string () const
    {
        return m_dayNames [m_day];
    }
};

const char * DayOfWeek::m_dayNames [] =
{
    "Monday", "Tuesday", "Wednesday", "Thursday"
    , "Friday", "Saturday", "Sunday"
};

int main()
{
    DayOfWeek day (3);

    std::string s = day;

    std::cout << s;  // says "Thursday"
    
    return 0;
}


Vorsicht, dreckiger Code ohne jede Sicherheit, aber es geht nur um den Operator.

Persönlich würde ich allerdings eine toString-Funktion vorziehen. Operator-Überladungen sind eine Spielwiese, auf der sich Lehrbuchschreiber und Dozenten gerne austoben. In der Praxis haben sie eine viel geringere Bedeutung, weil die Gefahr des Missverständnisses so groß ist.

ao
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: