[C++] scope-resolution operator. Nut?

Pagina: 1
Acties:

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:15

mulder

ik spuug op het trottoir

Topicstarter
* mulder heeft eigenlijk nooit echt over programmeren geleerd, en wilt nu toch een beetje de beginselen onder de knie krijgen, en C++ leren leek me daar wel geschikt voor.

En gelijk kom ik wat 'vreemds' tegen; de scope-resolution operator (::)
Neem dit stukje C++ proza:
C++:
1
2
3
4
5
6
7
  int x = 2;
  for (int i = 0; i < 10; i++)
  {
    int x = 4;
    cout << x << endl;    
    cout << ::x << endl;
  }


De eerste cout zou 4 moeten outputten, de tweede... 2. Buiten dat dit bijzonder onoverzichtelijk is, is er enig nut hiervoor? (Bovendien kwam het niet door de compiler van Dev-C++(Mingw?)) Nu las ik ook nog dat je functie die buiten de class staan, toch aan deze class kunnen worden toegewezen: is hier enig nut van?

Niet echt belangrijk, maar misschien is het interessant om eens een lichtje over te schijnen.

oogjes open, snaveltjes dicht


  • rollebol
  • Registratie: Mei 2000
  • Laatst online: 09-06 12:38
Bedoel je met functies die buiten de class staan misschien friend functions? Daar is zeker nut voor. Je kan zo bijvoorbeeld een functie die een ostream returnt maken die niet op het object zelf gedefinieerd is, maar wel bij de private members kan, zodat je cout << object << endl; kan doen.

Of is dat niet wat je bedoelt?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

De functie is niet helemaal buiten een class gedeclareerd, alleen gedefnieerd ;)

C++:
1
2
3
4
5
6
class A{
public:
    void foo();
}

void A::foo(){//doe iets}


[edit]
En je kan gewoon in de implementatie van die foo methode bij de members van A komen.

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:15

mulder

ik spuug op het trottoir

Topicstarter
rollebol schreef op 07 November 2002 @ 18:17:
Je kan zo bijvoorbeeld een functie die een ostream returnt maken die niet op het object zelf gedefinieerd is, maar wel bij de private members kan, zodat je cout << object << endl; kan doen.
Dat vroeg ik me idd wel af, of deze functie dan bij de private members kon komen. Maar dan vraag ik me wel af of dit wederom erg onoverzichtelijk is.

oogjes open, snaveltjes dicht


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Wat jullie bedoelen zijn open objects, en dat is iets dat c++ niet ondersteund :) Kijk maar naar mijn vorige reply en dan zie je wat 'functies gedefinieerd buiten classes' bedoelt wordt.

  • mulder
  • Registratie: Augustus 2001
  • Laatst online: 00:15

mulder

ik spuug op het trottoir

Topicstarter
* mulder denkt dat een open object een object is die niet gedeclareerd hoeft te worden in de class, maar dat dit object wel bij de private members kan. :? :/

oogjes open, snaveltjes dicht


  • whoami
  • Registratie: December 2000
  • Laatst online: 29-08 15:58
In jouw eerste voorbeeld geeft die scope resolution operator aan dat hij de waarde van x moet geven die niet in de 'eerste' scope zit, maar in de buitenste. In zo'n geval kun je eigenlijk het gebruik van de scope resolution operator vermijden door een betere naamgeving van variablen toe te passen.


Mbt de member functions in classes is het gewoon handig dat je in je class-definitie (die meestal in de header file staat), enkel de 'interface' van die class definieert. De implementatie ga je dan in de cpp file doen. (Iets wat mij stoort in C# en Java: als je een class hebt, moet je zowel de definitie en de implementatie binnen die class doen). Ik vind dat onoverzichtelijk. (Gelukkig hebben we in C# 'regions' en met VS.NET een 'collapsable editor').
Maar, om nog eens terug te komen: die functies zijn wel geimplementeert binnen de class, maar ze behoren wel degelijk tot die class. (Zie ook het voorbeeld van Alarmnummer).

https://fgheysels.github.io/


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Don Facundo schreef op 07 november 2002 @ 18:13:
* .oisyn heeft eigenlijk nooit echt over programmeren geleerd, en wilt nu toch een beetje de beginselen onder de knie krijgen, en C++ leren leek me daar wel geschikt voor.

En gelijk kom ik wat 'vreemds' tegen; de scope-resolution operator (::)
Neem dit stukje C++ proza:
C++:
1
2
3
4
5
6
7
  int x = 2;
  for (int i = 0; i < 10; i++)
  {
    int x = 4;
    cout << x << endl;    
    cout << ::x << endl;
  }


De eerste cout zou 4 moeten outputten, de tweede... 2. Buiten dat dit bijzonder onoverzichtelijk is, is er enig nut hiervoor? (Bovendien kwam het niet door de compiler van Dev-C++(Mingw?)) Nu las ik ook nog dat je functie die buiten de class staan, toch aan deze class kunnen worden toegewezen: is hier enig nut van?


Dat is niet correct, x is in dit stukje code niet onderdeel van de global namespace. In de global namespace staan alle variabelen en functies die niet in een andere namespace gedefinieerd zijn. Bijvoorbeeld:
C++:
1
2
3
int x;
void func ();
Klasse bla;


De complete namen van deze elementen zijn ::x, ::func en ::bla

Je kunt ook variabelen en functies in een namespace declareren:
C++:
1
2
3
4
5
namespace bla
{
    int x;
    void func ();
}


nu zijn de volledige namen ::bla::x en ::bla::func
Classes en structs introduceren een ook eigen namespace

Dit is handig als je bijvoorbeeld het volgende stukje code hebt:

C++:
1
2
3
4
5
6
int x;

void func (int x = 5)
{
    x = 4;   // welke wordt nu bedoeld?
}


In dit geval maak je gebruik van de locale variabele. Als je de globale x wilt gebruiken dan zul je ::x moeten schrijven

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.


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alarmnummer schreef op 07 november 2002 @ 18:26:
Wat jullie bedoelen zijn open objects, en dat is iets dat c++ niet ondersteund :) Kijk maar naar mijn vorige reply en dan zie je wat 'functies gedefinieerd buiten classes' bedoelt wordt.


wat zijn open objects?
Anyway, wat rollebol bedoelt zijn friend functions (en structs/classes)

C++:
1
2
3
4
5
6
7
8
9
10
11
12
class Blaat
{
friend void func (Blaat &);
private:
    int x;
};

void func (Blaat & b)
{
    b.x = 4; // func kan bij de private members van Blaat,
             // omdat het een friend van Blaat is
}

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.


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 05:00
(jarig!)
Ik neem aan dat Alarmnummer bedoelt, dat je 'elders' (in andere, nog niet bestaande source files) methoden aan een bestaande klasse kan toevoegen. In C++ kan dit niet direct, maar een vergelijkbaar effect kan bereikt worden met globale functies die een object als argument meekrijgen (wat in veel pure OO talen weer niet kan), maar dan heb je nog steeds alleen maar beschikking over 't niet-private deel van de klasse.

De "<<" en ">>" operators op C++ streams zijn een goed voorbeeld van hoe je dit in C++ oplost. De feitelijke stream klassen kunnen niet uitgebreid worden, maar er kunnen wel extra operators voor gedefinieerd worden (een operator is in C++ tenslotte ook maar gewoon een functie).

De mogelijkheid om extra methoden toe te voegen aan een klasse lijkt me moeilijk te combineren met het basisprincipe van encapsulatie en gerelateerde data en functionaliteit 'bij elkaar houden'.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

[nohtml]
Soultaker schreef op 07 november 2002 @ 20:13:
[...]

Ik neem aan dat Alarmnummer bedoelt, dat je 'elders' (in andere, nog niet bestaande source files) methoden aan een bestaande klasse kan toevoegen. In C++ kan dit niet direct, maar een vergelijkbaar effect kan bereikt worden met globale functies die een object als argument meekrijgen (wat in veel pure OO talen weer niet kan), maar dan heb je nog steeds alleen maar beschikking over 't niet-private deel van de klasse.
Ah dat... Ik kende het concept wel, maar ik wist de naam van het beestje niet :)

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.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Soultaker schreef op 07 november 2002 @ 20:13:
[...]
Ik neem aan dat Alarmnummer bedoelt, dat je 'elders' (in andere, nog niet bestaande source files) methoden aan een bestaande klasse kan toevoegen. In C++ kan dit niet direct, maar een vergelijkbaar effect kan bereikt worden met globale functies die een object als argument meekrijgen (wat in veel pure OO talen weer niet kan), maar dan heb je nog steeds alleen maar beschikking over 't niet-private deel van de klasse.
Inderdaad, en dat is dus precies hetgene wat een open object inhoudelijk meer kan dan een 'closed' object.
De "<<" en ">>" operators op C++ streams zijn een goed voorbeeld van hoe je dit in C++ oplost. De feitelijke stream klassen kunnen niet uitgebreid worden, maar er kunnen wel extra operators voor gedefinieerd worden (een operator is in C++ tenslotte ook maar gewoon een functie).
In principe is iedere statische functie daar een goed voorbeeld van. Ik vind het jammer dat de c++ compiler dit niet als een methode aanroep accepteerd:

public void werk(Persoon p);
werk(p@Timmerman){//mep spijker}
werk(p@Slager){//mep varken}

en dan kan je aanroepen met:
jan.werk(); of werk(jan)

Eigelijk gaat dit al weer iets verder, want dit is dus een pure single dispatch (gewoonlijk kan je dat alleen maar doen mbv polymorphisme). Eigelijk een beetje stom dat ze dit niet doorvoeren, want de onderdelen zijn allemaal al klaar. (Het enigste wat ze moeten doen is kijken of de 'closure' goed is. (er moet namelijk voor ieder persoontype een werkmethode zijn geimplementeerd)
De mogelijkheid om extra methoden toe te voegen aan een klasse lijkt me moeilijk te combineren met het basisprincipe van encapsulatie en gerelateerde data en functionaliteit 'bij elkaar houden'.
En dat is eigelijk ook meteen een van de problemen die ik heb met de 'klassieke' aanpak van oo. We gaan gewoon vet grote classes maken waarin de functionaliteit verspreid ligt over een hele zooi objecten. Ik denk dat je zo nu en dan een beetje af moet stappen van dit soort beperkingen. Een paradigma is een hulpmiddel, niet een doel :)

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Soultaker schreef op 07 november 2002 @ 20:13:
Ik neem aan dat Alarmnummer bedoelt, dat je 'elders' (in andere, nog niet bestaande source files) methoden aan een bestaande klasse kan toevoegen. In C++ kan dit niet direct, maar een vergelijkbaar effect kan bereikt worden met globale functies die een object als argument meekrijgen (wat in veel pure OO talen weer niet kan), maar dan heb je nog steeds alleen maar beschikking over 't niet-private deel van de klasse.
Je kunt een nog niet bestaande functie wel als friend vooruit declareren en 'm later pas implementeren, op die manier kom je wel bij de privates.

Ennuh, over de scope resolution operator:
C++:
1
2
3
4
5
6
7
8
9
10
11
namespace UserInterface
{
  class Button {...};    // Dit beschrijft een userinterface-element button
}

namespace Klerenmaker
{
  class Button {...};    // Dit beschrijft een knoop voor op je colbertje
}

Klerenmaker::Button     g_KlerenButton = new KlerenMaker::Button;

Da's al 1 overduidelijk nut.

En dan nu de statics:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
class SomeClass
{
  ...
  // Static functie
  static SomeClass*         Create();

  // Static member
  static const int              c_Constant;
};

SomeClass*          g_SomeClass = SomeClass::Create();

const int      SomeClass::c_Constant = 684;

Genoeg voorbeelden zo? :Y)

Professionele website nodig?


Verwijderd

curry684 schreef op 07 november 2002 @ 22:52:
[...]

Je kunt een nog niet bestaande functie wel als friend vooruit declareren en 'm later pas implementeren, op die manier kom je wel bij de privates.
Dat is extreem beperkt, met niet al teveel library code en minimale impact op de call syntax kun je veel flexibeler gebruikers member functions (met toegang tot privates) laten toevoegen:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class S
{
  float x;
 
  public:
 
    S (float x_) : x (x_) {}
 
    OPENOBJECT(ex)
};
 
struct new_member { typedef Generator<>::Make<float, float>::type types; };
 
template <> float S::ex<new_member> (float y)
{
  return x += y;
}
 
int main ()
{
  S s (1.2);
  std::cout << s.ex<new_member>(3.4);
}
Ik vind open objects overigens erg lelijk en zou een dergelijke constructie dan ook nooit gebruiken.
Pagina: 1