Objekt soll ture und oder false zurückgeben
-
Wie mach ich dass, das mein Objekt "obj" etwas zurückgibt? Was muss ich da überladen...wie geht das? "fstream" Objekte können ja auch etwas zurückgeben, also in einer if Bedingung z.B.: if(OBJEKT)....
Hier der Code:
#include <iostream> #include <fstream> #include <string> using namespace std; class crypt { public: crypt(const string &file_name); private: fstream file; }; crypt::crypt(const string &file_name) { file.open(file_name.c_str(), ios::out | ios::binary | ios::app); } int main() { crypt obj("H:/TEST.jea"); if(obj)..... else.... ..... return 0; }Muss ich da irgendwie "true" \ "false" überladen...geht sowas überhaupt? Hab des noch nie gemacht\gehört\gelesen

MfG
Stromberg
-
http://www.cpp-tutor.de/cpp/le12/le12_04.htm#cast
Lesen->Verstehen->Staunen
-
mit ueberladen erreichst du nur ne expliziete typumwandlung.
also das du sawas schreiben koenntest ...
crypt mycrypt("myfile.xyz"); if(mycrypt) { // ... } else { // ... } // ....Ist es das was du willst ?
Wenn ja, ich wuerd damit sehr vorsichtig sein.
Gibt faelle da macht es Sinn .... wenn die Bedeutung intuitiv ist, also das object irgendwas darstellt, was genau einen Stautus mit 2 zustaenden als die wichtigste eigenschaft hat ....Ansonsten sollte man die wirkung von namen der methoden ned unterschaetzen. Bei nem crypt object wuerd ich als user ned auf anhieb wissen, was nen true oder false als haupteigenschaft bedeuten soll
nenn mycrypt.isValid() wuerd mir dagegen etwas auf die spruenge helfen. Und man hat den vorteil ned in probleme mit den implizieten typkonvertierungen zu kommen.Ciao ...
-
#include <fstream> #include <string> class crypt { std::ofstream m_filestream; public: crypt(std::string const & file_name) : m_filestream(file_name.c_str(), std::ios_base::binary | std::ios_base::app) {} };... So wäre die Klasse schon besser!

Jetzt zu deiner Frage ... bei den Standardklassen wurde es meist über operator void* geregelt ...
class foo { bool m_error; public: foo() : m_error(false) {} operator void*() const { return m_error ? NULL : this; } public: void set_error(bool error = true) { m_error = error; } };Wenn jetzt ein Fehler auftritt, wird NULL zurück gegeben, sonst der Zeiger auf das Objekt selber:
foo inst; if (inst) std::cerr << "FEHLER: Es ist ein Fehler aufgetreten!" << std::endl; std::clog << "class foo => set error flag" << std::endl; inst.set_error(); if (inst) std::cerr << "FEHLER: Es ist ein Fehler aufgetreten!" << std::endl;... so, noch fragen?

-
(D)Evil schrieb:
so, noch fragen?

Ja: Wieso benutzt man 'void*' statt 'bool'? Welche Vorteile hat das? Welche Probleme hat man mit diesem Verfahren, und wie kann man sie (endgültig?) lösen?
Viel Spaß.

-
Konrad Rudolph schrieb:
(D)Evil schrieb:
so, noch fragen?

Ja: Wieso benutzt man 'void*' statt 'bool'? Welche Vorteile hat das? Welche Probleme hat man mit diesem Verfahren, und wie kann man sie (endgültig?) lösen?
bool-Werte können implizit in ints oder - je nach Kontext andere Typen - konvertiert werden, wenn der Kontext das erlaubt. Ein solcher Kontext sind zum Beispiel Operatoren. Eine Klasse, die einen Konvertierungsoperator nach bool besitzt, kann daher automatisch mit allen diesen Operatoren verwendet werden, auch wenn die Klasse diese Operatoren nicht selbst überlädt. Das ist eine allgemeine Gefahrenquelle von Konvertierungsoperatoren, die man auch aus diesem Grunde nur sehr sparsam einsetzen sollte. Die Gefährlichkeit dieser Konvertierung hängt offenbar vom Zieltyp und den Konvertierungsmöglichkeiten dieses Zieltyps ab.
Damit unser Operator in boolschen Kontexten eingesetzt werden können, muss der Zieltyp bool sein oder eine implizite Konvertierung in bool ohne Einsatz eines Konvertierungsoperators möglich sein, damit kommen in Frage:
1. arithmetische Typen
2. Aufzählungen
3. Zeiger auf Objekte, (Referenzen auf) Arrays
4. Zeiger auf Funktionen
5. void*
6. Zeiger auf Member oder Zeiger auf Memberfunktionen
Untersuchen wir diese Fälle der Reihe nach:
1. Arithmetische Typen: hier haben wir es mit einer Unmenge an impliziten Konvertierungen und möglicher Operatoren zu tun, Gleitkommatypen können nicht mit bitshift oder binärverknüpfenden Operatoren verwendet werden, ansonsten steht unabhängig vom Zieltyp nahezu die gesamte Menge an eingebauten Operatoren zur Verfügung; jede Wahl in dieser Kategorie ist daher in gleichem Maße sehr schlecht.
2. Aufzählungen: Aufzählungstypen können implizit in ints umgewandelt werden, damit gilt im Grunde das unter 1. gesagte. Da Aufzählungstypen UDTs sind, kann man Operatoren für sie überladen, damit wäre es möglich, die ungewollten Oeratoren zu unterdrücken (indem wir dann einen Compilerfehler provozieren), das hilft uns aber nicht in Fällen, in denen keine überladbaren Operatoren vorkommen, zum Beipsiel beim Funktionsaufruf: ein Aufzählungstyp kann Argument einer Funktion sein, die einen int-Parameter hat.
3. Zeiger auf Objekte, (Referenzen auf) Arrays: Zeiger erlauben Zeigerarithmetik und eine Reihe anderer Operatoren, gleiches gilt für lvalue-Arrays, diese können implizit in Objektzeiger konvertiert werden.
4. Zeiger auf Funktionen: sind eine relative gute Wahl, außer Konvertierung in bool kann man nur unäres * und () auf sie anwenden. Es geht noch besser.
5. void* - Hiermit kann man wenig anfangen, die meisten Operatoren benötigen erst eine Konvertierung in bool, die meisten anderen sind eher ungefährlich, außer möglicherweise Cast-Operatoren, allerdings tritt es gehäuft als Parameter bestimmter Funktionen auf. Das ist daher eine recht gute Wahl, gut genug um von der Standardbibliothek verwendet zu werden.
6. Zeiger auf Member und Zeiger auf Memberfunktionen: mit diesen Zeigern kann man keine Arithmetik betreiben, lediglich ->* und .* sind auf sie anwendbar, vorausgesetzt man hat einen passenden Zeiger oder ein passendes Objekt - das kann man einfach verhindern, indem man die betreffende Klasse private macht. Als Funktionsargumente können sie im Grunde nur in Templatefunktionen verwendet werden (weil die Klasse private ist), eine solche Funktion müsste allerdings recht seltsam sein: einerseits müsste die Klasse deduziert werden, andererseits kann das nicht mit dem Parameter geschehen, der unseren Zeiger entgegennimmt, denn dann würde der Typ dieses Parameters ja als der der Klasse deduziert werden - hier besteht also keine Gefahr. Auch bei Casts besteht keine Gefahr: lediglich die Konvertierung in einen Zeiger auf ein Member auf eine abgeleitete Klasse wäre möglich, und eine solche Klasse kann gar nicht definiert werden. Das ist unter dem Sicherheitsaspekt daher die optimale Wahl für das safe_bool idiom. Andererseits sind Memberzeiger relativ komplexe Gebilde und insbesondere zu der Zeit, als die Standardbibliothek entwickelt wurde, war die Compilertechnik nicht so weit, dieses Idiom ohne Overhead umzusetzen, während dies bei void* eine recht simple Angelegenheit für den Compiler ist (jedenfalls für inline-Konvertierungsoperatoren). Mit modernen Compilern ist das normalerweise kein Problem mehr, und z.B. in Boost wird generell ein solcher Typ verwendet.
-
camper!

Dass Du das weißt, weiß ich. …
-
Aber trotzdem sehr schöner Beitrag

-
-
(D)Evil schrieb:
#include <fstream>
#include <string>class crypt
{
std::ofstream m_filestream;public:
crypt(std::string const & file_name)
: m_filestream(file_name.c_str(), std::ios_base::binary | std::ios_base::app)
{}
};Was ist "ios_base"? Ich kenn nur "ios", was ist da der Unterschied? In meinem C++ Buch steht, das "ios_base" einfach nur die Basisklasse von "basic_ios" (ios) ist. Aber warum soll ich dann "ios_base" und nicht "ios" verwenden?
Ansonsten sehe ich keinen Unterschied zu meiner Klasse. Warum verwendest du kein "ios_base::out"?
Und "m_filstream" muss ein "fstream" Objekt sein, da ichs lesen und schreiben möchte!!!
MfG
Stromberg
-
(D)Evil schrieb:
so, noch fragen?

Warum macht man sowas? Wieso nicht einfach eine einfache Methode isOK()? Wäre doch einfacher verständlich und lesbarer.
-
Stromberg: Naja ne Initialisierungsliste ist schon was anderes als das was du gemacht hast.
Und "m_filstream" muss ein "fstream" Objekt sein, da ichs lesen und schreiben möchte!!!
Warum öffnest du es dann nur zum schreiben?!
Warum verwendest du kein "ios_base::out"?
Warum sollte ich? Ist nunmal ein std::ofstream-Objekt. Da ist es klar, das es std::ios_base::out sein muss!
-
Achja und @die Fragen aller Fragen, @all: http://www.artima.com/cppsource/safebool.html vllt einfach mal durchlesen ... hilft ...