Signal/Slot, public signal?
-
Was ist eure Meinung bezüglich öffentlichem Signal (hier: value_changed)?
Alternativ wäre z.B. subscribe(..) / unsubscribe(..) anzubieten (und das Signal privat machen), was sicher beim Debuggen hilfreich ist.Falls mit Registrier-Methoden:
- Wie benennt ihr die Methoden, falls es mehrere Signals gibt?
- Wie benennt ihr die Methoden, dass die Namen nicht zu lange werden?
- typedef'd ihr das signal / slot / connection?#include <boost/signals2.hpp> class node { public: node() : value_(0) { } boost::signals2::signal<void (node&)> value_changed; long get_value() const { return value_; } void set_value(long value) { value_ = value; value_changed(*this); } private: long value_; };
-
Niemals, niemals, niemals Member-Variablen public machen.Punkt! Selbst protected ist unverzeihlich.
-
Artchi schrieb:
Niemals, niemals, niemals Member-Variablen public machen.Punkt! Selbst protected ist unverzeihlich.
Stirb. Membervariablen public machen, wo es Sinn macht. Das hier ist allerdings kein Fall.
-
?
#include <boost/signals2.hpp> class node { public: node() : value_(0) { } long get_value() const { return value_; } void set_value(long value) { value_ = value; value_changed_(*this); } typedef boost::signals2::signal<void (node&)> signal_type; boost::signals2::connection subscribe_value_changed(signal_type::slot_type slot) { return value_changed_.connect(slot); } void unsubscribe_value_changed(boost::signals2::connection connection) { value_changed_.disconnect(connection); } private: long value_; signal_type value_changed_; };[Edit]
Code korrigiert
-
Brauchst du ein Unsubscribe überhaupt? Du kannst ja auf einem
connection-Objekt direktdisconnect()aufrufen...
-
314159265358979 schrieb:
Membervariablen public machen, wo es Sinn macht.
Und wo wäre das?
-
Nexus schrieb:
Brauchst du ein Unsubscribe überhaupt? Du kannst ja auf einem
connection-Objekt direktdisconnect()aufrufen...Habe ich mich auch gefragt. Es kommt mir irgendwie komisch vor wenns nur ein subscribe...(..) gibt. So unsymmetrisch.
Technisch ist das unsubscribe nicht nötig.
-
std::pair zum Beispiel. Oder Server und Port eine Socketklasse.
-
theta schrieb:
Habe ich mich auch gefragt. Es kommt mir irgendwie komisch vor wenns nur ein subscribe...(..) gibt. So unsymmetrisch.
Bei ähnlichen Klassen bei mir habe ich meist ein
Connect()für die Registrierung sowie einClearConnections(), um alle Slots auf einmal zu entfernen. Aber keinDisconnect()für einen einzelnen Slot.Falls ein
unsubscribe()keine zusätzliche Funktionalität bietet, würde ich es nicht anbieten. Sonst fragt sich der Benutzer, wieso er deine Methode aufrufen soll, wenn er den Slot mitconnection::disconnect()ebenfalls trennen kann...
-
@Nexus:
Und was hast Du wie getypedef'd?
-
Hier mal ein Beispiel einer Timer-Klasse, die beim Ablaufen der Zeit Callbacks auslösen kann (nur der relevante Teil des APIs):
class TriggeringTimer { public: typedef std::tr1::function< void(TriggeringTimer&) > Listener; public: Connection Connect(const Listener& listener); void ClearConnections(); };Wobei die Klasse halt nur ein einzelnes Signal enthält, daher kann ich allgemeine Namen wie "Listener" verwenden.
Ein Fall, in dem ich mehrere Signale hatte: Vor einiger Zeit schrieb ein paar GUI-Klassen für SFML, allerdings entwickelte ich sie nie ganz fertig. Das sah dann z.B. folgendermassen aus: Keine
ClearConnections()-Funktionen, und dietypedefs sind spezifischer:class TextField { public: Connection ConnectTextEvent(const TextEventListener& listener); Connection ConnectClick(const ClickListener& listener) };Ursprünglich hatte ich Bezeichner wie
AddTextEventListener(), aber das war mir auf Dauer zu umständlich.
-
@314159265358979: std::pair ist nicht das beste Beispiel für den klassischen Einsatzzweck von Objektorientierung. Die üblichen Überlegungen wie Schnittstellen-Design oder Zugriffskontrolle fallen gar nicht an, dank der Einfachheit der Datenstruktur.
Und
Oder Server und Port eine Socketklasse.
Das hat sich mir nicht erschlossen.
-
@Nexus: Danke.
-
Markward schrieb:
Das hat sich mir nicht erschlossen.
class socket { public: const std::string server; const short port; }
-
Das sind keine Membervariablen, das sind Konstanten. Bäh.
-
Das sind (konstante) Membervariablen.
-
Konstante Variablen, soso. Na wenn du das so siehst

Ich persönlich halte es aber für sinnvoll, (variable!) Membervariablen grundsätzlich hinter einer Methode zu verbergen. Einschränkung dabei ist, dass die Klasse schon irgendetwas "können" muss. Für jeden Wert, der sich die ganze Anwendung über vermutlich nicht ändert und halt einmal im Konstruktor initialisiert wird einen Getter und Setter anzubieten ist fraglich (siehe std::pair, color_rgb o.ä.).
Sobald aber ein Wert potentiell irgendwelchen implementierungsabhängigen Manipulationen unterworfen ist, sollte man den Wert nach außen auch nur durch eine Methode als saubere Schnittstelle weiterreichen. Und Datenelemente daher private machen. Ansonsten das, was Meyers sagt.
Aber die Diskussion gabs hier bestimmt auch schon öfter.
-
314159265358979 schrieb:
Markward schrieb:
Das hat sich mir nicht erschlossen.
class socket { public: const std::string server; const short port; }Also ich würde nichtmal sowas public machen.
Mal ganz davon abgesehen, dass der Name "socket" äusserst fraglich ist, für ein Ding das per Definition immer einen Port "hat" und einen Server "per Namen kennt". Das riecht eher nach einer "Connection".
-
Ein Socket ist eine Eindeutige Identifizierung des Endpunkts einer Verbindung. Zu eindeutig gehört nunmal auch Host und Port.
-
Und was ist mit Serversockets?