Signal/Slot, public signal?
-
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?
-
Was soll denn ein Serversocket sein? Socket ist Socket.
-
314159265358979 schrieb:
Ein Socket ist eine Eindeutige Identifizierung des Endpunkts einer Verbindung. Zu eindeutig gehört nunmal auch Host und Port.
Nein.
Ein Socket ist ein Socket.
Der kann auch "unbound" sein.Was das Thema Endpunkt angeht: was soll der String "server" da bitte bedeuten?
Soll das die lokale Adresse sein auf die der Socket gebunden ist? Wieso heisst der dann "server" und nicht "host" o.ä. Und wieso als String? Du kannst einen Socket schliesslich nicht auf eine URL binden, sondern nur auf eine Adresse (bzw. auch auf mehrere, wenn man z.B. auf 0.0.0.0 bindet).
Davon abgesehen kann man sich die Info auf welchen Port/Adresse ein Socket gebunden ist vom System holen. Die Infos permanent in Membervariablen abzuspeichern ist also redundant.
-
Ist ein wenig OT das Thema Socket.

-
hustbaer schrieb:
Der kann auch "unbound" sein.
Wie du den verwendest, zeigst du mir.
hustbaer schrieb:
Was das Thema Endpunkt angeht: was soll der String "server" da bitte bedeuten?
Soll das die lokale Adresse sein auf die der Socket gebunden ist? Wieso heisst der dann "server" und nicht "host" o.ä. Und wieso als String?
Ich bin hier so frei und quetsche hier nen Resolver mit nem Socket in eine Klasse. Sehr komfortabel. gethostbyname() ist ja auch nur ein Aufruf, spricht für mich nichts dagegen, das dazu zu geben.
hustbaer schrieb:
Du kannst einen Socket schliesslich nicht auf eine URL binden, sondern nur auf eine Adresse (bzw. auch auf mehrere, wenn man z.B. auf 0.0.0.0 bindet).
Ich binde ihn auf die erste IP, auf die die URL verweist.
hustbaer schrieb:
Davon abgesehen kann man sich die Info auf welchen Port/Adresse ein Socket gebunden ist vom System holen. Die Infos permanent in Membervariablen abzuspeichern ist also redundant.
Mag sein. Ich weiß zwar nicht wie, aber ich glaubs dir einfach mal.
-
@theta:
Ja, ist OT
Zurück zum Thema:
Ich mache das - in meinem aktuellen Projekt - im Prinzip so wie du, mit zwei (IMO unwesentlichen) Unterschieden:
- Ich verwende nicht boost::signals(2) sondern was selbstgestricktes
- Ich hab keine public Member, dafür aber nen Getter der nen shared_ptr<Event> zurückgibt (Event ist bei mir das, was bei signals(2) das "signal" ist)
Ändert aber nix daran, dass man vollen Zugriff auf das "signal" (Event) hat.
Register/Unregister Funktionen führen IMO zu viel zu viel Code-Duplizierung. Einerseits muss man innerhalb der Klasse die ganzen Attach/Detach Funktionen schreiben. Andrerseits kann man auch ausserhalb der Klasse viel weniger Code wiederverwenden. Da es z.B. kein gemeinsames Interface gibt, kann man auch keine Guard-Klassen schreiben die ein Attach im Ctor und ein Detach im Dtor machen. Zu erlauben dass das "signal" (in dem Fall die Klasse mit den Attach/Detach Funktionen) zerstört wird, während noch Listener draufhängen, ist in der Variante auch nicht einfach.
In Summe sind es mir einfach zu viele Nachteile.
Das einzige was mich an der "signal freilegen" Variante stört, ist, dass man von ausserhalb der Klasse das "signal" triggern kann (
node.value_changed();). OK, muss man halt einfach nicht machen. In grösseren Projekten, mit z.T. mässig disziplinierten Mitarbeitern, könnte das aber ein echter Nachteil sein.Wenn man eine selbstgebackene Implementierung schreibt, könnte man das allerdings umgehen, indem man den Teil wo sich die "Listener" draufhängen können aus dem signal "raustrennt".
Grob skizziert:
class connection_point { public: connection attach(...); void detach(connection c); // ... // vermutlich wird hier ein friend class event; // angebracht sein }; class event { public: void fire(); connection_point& get_connection_point() const; // ... }; class foo { public: connection_point& value_changed() { return m_value_changed_event.get_connection_point(); } int get_value() const { return m_value; } void set_value(int val) { if (val != m_value) { m_value = val; m_value_changed_event->fire(); } } private: int m_value; event m_value_changed_event; };
-
Also
get_connection_point()sollte entweder nichtconstsein, oder aber eine const Referenz zurück geben!
-
bmario schrieb:
Also
get_connection_point()sollte entweder nichtconstsein, oder aber eine const Referenz zurück geben!Naja, const ist Definitionssache

Ich hab das absichtlich so geschrieben. Der Gedanke dahinter war: mit dem connect/disconnect ändert man ja normalerweise nichts, was irgendwen interessieren würde (ausser dem Programmteil der connected/disconnected). Von daher kann man es ruhig als "const" Operation definieren.
Und es könnte in bestimmten Situationen praktisch sein.Aber man kann das An- und Abmelden von Listenern genau so gut als "non const" ansehen. Dann gehört das "const" natürlich weg.
Dafür muss man im Client Code vermutlich ein paar mal zusätzlich "mutable" schreiben.
-
@hustbaer: Danke für deine Sichtweise zum Thema.
