[C++] Friend class, ook alle extends

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Hallo tweakers,

Ik ben bezig met het schrijven van een HTTP Server in C++. Dit lukt allemaal aardig. Ik heb nu alleen ergens iets onhandigs.

Ik heb een server functie, deze zit in een oneindige loop en accept clients. Voor elke client word er dan een apparte thread aan gemaakt (QThread). In deze thread word het http protocol behandeld. Gaat dit allemaal ok, dan word er een site handler aan geroepen (aan de hand van 'virtual hosts'). Maar deze site handler is aan apparte class, dus los van de http handler etc.

Het komt dus hier op neer, ik heb de site handler een friend class gemaakt van de http handler. De http handler called een functie in de sitehandler (static) en geeft een object van de http handler mee (deze http handler bevat function voor de header, body, etc.) Maar zodra ik een site handler schrijf, dus een extend op de site handler, kan deze geen protected functies aan roepen op de pointer naar de http handler. Ik heb dit als volgd opgelost:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class HTTPHandler : .... {
    ...
    void echo(const string& str);
    void set_header(const string& key, const string& value);
    ...
    friend class SiteHandler;
};

class SiteHandler{
    protected:
        void echo(HTTPHandler* root, cont string& str){ root->echo(str); }
        void set_header(HTTPHandler* root, const string& key, const string& value){ root->set_header(key, value); }
};

class Example_Com : public SiteHandler{
    protected:
        ...
        static handler(HTTPHandler* root){
                set_header(root, "content-type", "text/html");
                echo(root, "bla\n");
                ...
        }
        ...
};


Het is misschien ook handig om te weten dat de SiteHandlers 'los van de source' worden toegevoegd. Daar mee bedoel ik, de source achter de hele server etc. is gewoon standaart, maar je kan zelf dus apart sites toevoegen door in een map site handlers toe te voegen.

Maar is het ook mogelijk om in de HTTPHandler alle extends van SiteHandler ook friend classes te maken?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik snap eigenlijk niet zoveel van het nut van je class hierarchy. Waarom moet Example_Com van SiteHandler overerven, terwijl hij (in je voorbeeld althans) alleen wat functies van z'n base class aanroept? En waarom zijn die specifieke functies private, zodat je überhaupt friends nodig hebt? Je zou ook kunnen overwegen om die functies of gewoon public te maken, of om ze te abstraheren in een aparte interface die vervolgens alleen aan subclasses gecommuniceerd worden.

Anyway, om je vraag te beantwoorden: nee, dat kan niet.

Overigens, de juiste terminologie voor wat jij "extends" noemt is gewoon "subclasses" of "derived classes" 8)7

[ Voor 4% gewijzigd door .oisyn op 19-05-2009 13:42 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • farlane
  • Registratie: Maart 2000
  • Laatst online: 15:26
Is een SiteHandler een HTTPHandler? Je naamgeving suggereert dat SiteHandler ook een HTTPHandler is en in dat geval zou je deze een subclass van HTTPHandler kunnen maken. ( En HTTPHandler misschien een abstracte class? )

Somniferous whisperings of scarlet fields. Sleep calling me and in my dreams i wander. My reality is abandoned (I traverse afar). Not a care if I never everwake.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Ik ben van 'huis uit' een php programmeur en heb mij (net zoals php) zelf aan geleerd. Dus ik heb denk ik de terminologie van php overgenomen, en natuurlijk mijn eigen terminologie ;)

Ik zou idd de functie public kunnen maken, maar protected is er juist voor dat iemand die de class aan maakt de functie binnenin niet kan aan roepen.

Iemand kan dan namelijk best dit doen:
C++:
1
2
HTTPHandler request(server.accept());
request.echo("bla");

Maar dat zou niet moeten kunnen, want echo mag pas aangeroepen worden zodra de header is uitgelezen etc.

Maar ja, als je dat gewoon niet doet ;) dan is heb je die friend idd niet nodig.

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ok, maar laat nu dan eens met een stukje code zien hoe je volgens jou wel zou moeten werken? Want vooralsnog is je SiteHandler superklasse vrij doelloos. Hij definieert geen gedrag en hij is niet polymorph. Het enige wat ie doet is wat calls doorrouten naar HTTPRequest. Waarom zou je daarvan willen overerven?

[ Voor 54% gewijzigd door .oisyn op 19-05-2009 14:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
@farlane

Ik kan de SiteHandler geen subclass laten zijn van HTTPHandler omdat de SiteHandler 's worden 'geregistered' bij het linken / compile. Ik weet niet hoe ik dat anders kan noemen, ik zal wel met voorbeeld laten zien:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include "../src/sitehandler.hpp"
class example_com : public SiteHandler{
    public:
        // Constructor
        example_com(){
            // Register Handler
            registerHandler(&example_com::siteHandler);
        }
    
    protected:
        // Site Handler
        static bool siteHandler(HTTPHandler* root) throw(sckt::Exc){
            // Handle the site
            echo(root, "bla"); // echo is van SiteHandler, want deze is friend class van HTTPHandler
        }
};

// Register handler
example_com _example_com; // hier word de handler registered


Met deze structuur worden er aan een vector door de registerHandler functie handler function pointers toegevoegd voordat de main functie aangeroepen word. Ik heb dit verzonnen als alternatief voor dynamic libraries omdat ik daar nog geen niks van snap. Maar zoals je kunt zien, om die manier wil je niet de sitehandler een subclass of van de HTTPRequest, want dan zou je gelijk een HTTP request af handelen (en een QThread opstarten).

Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
@.oisyn
Ik snap je vraag niet helemaal. Maar:
C++:
1
2
HTTPHandler request(server.accept());
request.echo("bla"); // COMPILER ERROR, protected functie

zou dus niet moeten kunnen.

En mijn alle eerste post in deze topic werkt al wel, maar ik een beetje omslachtig.

[EDIT op oisy EDIT ;P ]
Kijk eens naar mijn post hier boven.

[EDIT]
Er zitten nog meer functie in de SiteHandler die nodig zijn, maar die postte ik niet omdat ik dacht dat deze niet relevant waren.

[ Voor 26% gewijzigd door vdvleon op 19-05-2009 14:28 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Mijn vraag is wat wél zou moeten kunnen :). Maar je laatste voorbeeld maakt eigenlijk al een boel duidelijk, namelijk dat je design compleet flawed is ;). SiteHandler heeft idd geen doel, zoals ik al dacht. Het doel dat jij 'm gegeven hebt is het friend probleem oplossen, maar dat is sowieso al een verkeerde aanpak.

Handiger is als je SiteHandler een interface is, die bijvoorbeeld een handleSite() method definieert. Je klasse Example_com is dan een subklasse van die SiteHandler, en implementeert handleSite(). Je HTTPHandler roept dan handleRequest() aan op de juiste SiteHandler (jouw Example_com dus). Als je die echo() method e.d. echt af wil schermen kun je ervoor kiezen om met handleRequest() nog een extra object mee te geven, waarop je de echo() op aan kunt roepen. Dit object is geassocieerd met dat specifieke request, en dient ter communicatie van en naar client.

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class HTTPRequest
{
    HTTPHandler * getHandler() = 0;
    void echo(const string & str) = 0;
    string getHeader(const string & header) const = 0;
    void setHeader(const string & header, const string & value) = 0;
};

class SiteHandler
{
public:
    virtual bool handleRequest(HTTPRequest * pRequest) = 0;
};

class Example_com : public SiteHandler
{
public:
    Example_com()
    {
        registerHandler(this);
    }

    virtual bool handleRequest(HTTPRequest * pRequest)
    {
        pRequest->echo("bla");
    }
};


HTTPRequest is een interface die intern in HTTPHandler wordt geïmplementeerd. Niemand kan die functies dus aanroepen adhv een HTTPHandler, want niemand heeft een instance naar een HTTPRequest. Alleen de sitehandler die verantwoordelijk is voor dat specifieke request heeft dat object, en gebruikt dat om te communiceren met de client.

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vdvleon
  • Registratie: Januari 2008
  • Laatst online: 08-06-2023
Misschien moet ik eff duidelijk een class structuur laten zien (met de juiste namen, lol).

Ik gebruik een socket systeem van sckt.

class sckt::TcpSocket
class sckt::TcpServer

class Client : sckt::TcpSocket // voeg std::string toe voor read / write
class Server : sckt::TcpServer // accept TcpSocket naar Client

class ThreadedClient : Client, QThread // maak threaded en voeg wat destructor functionaliteit toe

class HTTPClient : Threaded Client // Handle HTTP protocol

class PPPRequestHandler : HTTPClient // de echo, flush, set_header, etc. functions en sitemodule finder, zoekt de juiste sitemodule voor de Host header (dus example.com door example_comModule, localhost door localhostModule, etc. )

class SiteModule // Met functionaliteit die kijkt voor de huidige site settings, dus of het localhost is, if example.com etc. en de static siteHandler functie die word aan geroepen als PPPRequestHandler vind dat deze de juiste sitemodule is.

Ik hoop dat je me systeem een beetje volgd

[EDIT]
Op programmeer gebied (in oop) moet ik waarschijnlijk nog veel leren ja. Maar gelukkig begin ik volgend jaar ook met Informatica aan de radboud (als het goed is).

[ Voor 7% gewijzigd door vdvleon op 19-05-2009 14:52 ]

Pagina: 1