[c++] mag protected functie niet aanroepen!?

Pagina: 1
Acties:

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Als ik het volgende compileer in msvc++ 6:


code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class A 
{ 
 protected: 
  virtual void Func() = 0; 
}; 

class B : public A 
{ 
 protected: 
  virtual void Func(); 
  void Foo( A *bar ); 
}; 

void B::Foo( A *bar ) 
{ 
 bar->Func(); 
}

Zeurt hij dat het aanroepen van Func() op regel 16 niet mag. Waarom?

Ik heb het idee dat msvc de betekenis van "protected" niet helemaal begrijpt, en denkt dat het ook betrekking heeft op verschillenen tussen instanties i.p.v. classes (want
this->Func() i.p.v. bar->Func() mag wél). Terwijl dat volgens mij niet echt is wat mr. Stroustrup destijds voor ogen had...!?

[ Voor 3% gewijzigd door Jace / TBL op 27-10-2004 11:50 ]


  • Robtimus
  • Registratie: November 2002
  • Laatst online: 20:29

Robtimus

me Robtimus no like you

g++ zeurt er anders ook over:
test.cpp: In member function `void B::Foo(A*)':
test.cpp:4: `virtual void A::Func()' is protected
test.cpp:16: within this context

More than meets the eye
There is no I in TEAM... but there is ME
system specs


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Hmja, A::Func is protected, dat is precies wat ik wil: dat alleen A en afgeleiden van A bij Func kunnen, en verder niets. Dat is toch de betekenis van protected, of ben ik nu gek?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik denk dat jij de betekenis van protected niet helemaal begrijpt ;)

Protected wil zeggen dat je in een class bij de members van de base class mag. De eigen base class dus, niet een andere instantie van de base class.

Anders heeft die protection weinig nut, als je dan bij een protected member wilt maak je gewoon even een afgeleide van de class die vervolgens de juiste members aanroept op een hele andere instantie dan z'n eigen base class. Dat zou een beetje raar zijn :)

Heej, ben jij niet een (ex-)scener?

[ Voor 42% gewijzigd door .oisyn op 27-10-2004 12:05 ]

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Het klopt wel dat het niet mag:

code:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
1 When a friend or a member function of a  derived  class  references  a
  protected nonstatic member of a base class, an access check applies in
  addition  to  those  described  earlier  in this clause.4) Except when
  forming a pointer to member  (_expr.unary.op_),  the  access  must  be
  through  a  pointer  to,  reference to, or object of the derived class
  itself (or any class derived from that class)  (_expr.ref_).   If  the
  access is to form a pointer to member, the nested-name-specifier shall
  name the derived class (or any class derived from that class).  [Exam-
  ple:

  _________________________
  4) This additional check does not apply to other members, e.g.  static
  data members or enumerator member constants.

          class B {
          protected:
              int i;
              static int j;
          };

          class D1 : public B {
          };

          class D2 : public B {
              friend void fr(B*,D1*,D2*);
              void mem(B*,D1*);
          };
          void fr(B* pb, D1* p1, D2* p2)
          {
              pb->i = 1;  // ill-formed
              p1->i = 2;  // ill-formed
              p2->i = 3;  // ok (access through a D2)
              p2->B::i = 4;  // ok (access through a D2, qualification ignored)
              int B::* pmi_B = &B::i;    // ill-formed
              int B::* pmi_B2 = &D2::i;  // ok (type of &D2::i is "int B::*")
              B::j = 5;   // ok (because refers to static member)
              D2::j =6;   // ok (because refers to static member)
          }
          void D2::mem(B* pb, D1* p1)
          {
              pb->i = 1;  // ill-formed
              p1->i = 2;  // ill-formed
              i = 3;      // ok (access through `this')
              B::i = 4;   // ok (access through `this', qualification ignored)
              j = 5;      // ok (because refers to static member)
              B::j = 6;   // ok (because refers to static member)
          }
          void g(B* pb, D1* p1, D2* p2)
          {
              pb->i = 1;  // ill-formed
              p1->i = 2;  // ill-formed
              p2->i = 3;  // ill-formed
          }
   --end example]

Met name dus regel 41 en 43.

[ Voor 3% gewijzigd door Zoijar op 27-10-2004 12:16 ]


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op 27 oktober 2004 @ 12:03:
Heej, ben jij niet een (ex-)scener?
Ja, ik herkende hem ook al :) Samen met Nix toch?

  • gammuts
  • Registratie: April 2001
  • Laatst online: 03-04 11:25
.oisyn schreef op 27 oktober 2004 @ 12:03:
Ik denk dat jij de betekenis van protected niet helemaal begrijpt ;)
Lijkt mij ook. Ik ben dit ook een keer tegengekomen. Frustraties alom, maar achteraf is het "logisch" dat het niet mag. Denk nog eens goed na wat protected inhoud of spiek even op bijv:

http://msdn.microsoft.com...s/vccelng/htm/cntrl_3.asp

use strict; use warnings;


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
.oisyn schreef op 27 oktober 2004 @ 12:03:
Ik denk dat jij de betekenis van protected niet helemaal begrijpt ;)

Protected wil zeggen dat je in een class bij de members van de base class mag. De eigen base class dus, niet een andere instantie van de base class.
Ok, maar waarom mag het dan wel als je het type van bar (in Foo) van A* naar B* verandert? Dan gebruik je toch evengoed een functie van een baseclass van een andere instantie?
Anders heeft die protection weinig nut, als je dan bij een protected member wilt maak je gewoon even een afgeleide van de class die vervolgens de juiste members aanroept op een hele andere instantie dan z'n eigen base class. Dat zou een beetje raar zijn :)
Ja, als je dat soort dingen wilt forceren kan het altijd natuurlijk... Als ik "#define private public" neerzet kan ik overal bij, dus wat dat betreft heeft heel die shit geen zin :)

Ik dacht trouwens nog dat het voor dit probleem (dat je door af te leiden protected dingen toch public toegankelijk kon krijgen) misschien zou uitmaken of je het in die afgeleide class alleen vanuit protected functies doet. Daarom is Foo hier ook protected, ik expose zo nog steeds niks naar buiten (alhoewel het niks uit lijkt te maken).
Heej, ben jij niet een (ex-)scener?
ja, klopt :-)

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:33
JaceTBL schreef op 27 oktober 2004 @ 12:18:
[...]

Ok, maar waarom mag het dan wel als je het type van bar (in Foo) van A* naar B* verandert? Dan gebruik je toch evengoed een functie van een baseclass van een andere instantie?
Maar je gebruikt een instance van hetzelfde type.

https://fgheysels.github.io/


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Ja, hetzelfde type mag altijd 'bij zichzelf'. Dat is hetzelfde met bv copy constructors.

C++:
1
2
3
4
5
6
7
class A {
   int x;
public:
   A& operator=(const A& src) {
      this->x = src.x;
   }
};

Note dus dat src.x hier zelfs private is.

[ Voor 15% gewijzigd door Zoijar op 27-10-2004 12:24 ]


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
gammuts schreef op 27 oktober 2004 @ 12:12:
Lijkt mij ook. Ik ben dit ook een keer tegengekomen. Frustraties alom, maar achteraf is het "logisch" dat het niet mag. Denk nog eens goed na wat protected inhoud
Ik dacht altijd: alleen toegankelijk voor class waar hij toebehoort en afgeleide classes (en dat tweede maakt het verschil met private).
Link deed het niet helemaal, neem aan dat je dit bedoelde:
msdn zegt:
Class members declared as protected can be used only by the following:

• Member functions of the class that originally declared these members.
• Friends of the class that originally declared these members.
• Classes derived with public or protected access from the class that originally declared these members.
• Direct privately derived classes that also have private access to protected members.
Geen woord over instanties.

Verderop staat echter nog dit:
Protected members that are not declared as static are accessible to friends and member functions in a derived class only through a pointer to, reference to, or object of the derived class.
Dat verklaart de error, de logica hiervan ontgaat me echter. Waarom protected functies van onderliggende classes alleen van jezelf mogen aanroepen, en niet op andere instanties? Diezelfde logica geldt namelijk niet voor private, aangezien het volgende ook gewoon mag:
code:
1
2
3
4
5
6
7
8
9
10
11
12
class A
{ 
 private:
  void PrivateFunc();
 public:
  void PublicFunc( A *a );
}; 

void A::PublicFunc( A *a )
{
 a->PrivateFunc(); // niks geen gezeur over andere instanties hier
}

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoijar schreef op 27 oktober 2004 @ 12:12:
[...]

Ja, ik herkende hem ook al :) Samen met Nix toch?
Nou werk ik tegenwoordig voor diezelfde Nix ;)

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dit is het idee:
Afbeeldingslocatie: http://www.cs.vu.nl/~fasmit/inher.jpg
Je kan dus wel via de tweede instantie, met 'this' naar boven. Of eerst naar boven, en dan opzij naar de tweede instantie, maar niet schuin.

Dat een class zelf access heeft tot andere instanties is logisch, je zit dan namelijk al in die class. Het is en gesloten cirkeltje dat nooit misbruikt kan worden. Als je die member aan kan passen, dan kan je ook de variabele zelf aanpassen naar eventueel public. Je kan dus niet ergens bij dat iemand anders heeft gemaakt en private declared is.

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
.oisyn schreef op 27 oktober 2004 @ 12:32:
Nou werk ik tegenwoordig voor diezelfde Nix ;)
Doe ze de groeten daar :) (zeg was jij toen niet een keer mee wezen voetballen in Arnhem?)

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op 27 oktober 2004 @ 12:32:
Nou werk ik tegenwoordig voor diezelfde Nix ;)
Grappig. Dat waren toch wel de mensen waar ik als 13 jarig onderdeurtje enigszins tegenop keek vroeger, op die parties etc :) En kijk nu, the apprentice has become the master? ;)) hehe j/k

  • IJnte
  • Registratie: Juni 2003
  • Laatst online: 19-05 12:01
Ik heb zelf ook zitten klooien met classes. Ik heb zelf er veel geleerd van de tutorial op cplusplus.com. Kijk eens even of je hier wat aan hebt. Hier staat ook de reden van protected in een class in.

Exploring the world by bicycle! cyclingsilk.wordpress.com


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

JaceTBL schreef op 27 oktober 2004 @ 12:28:
Dat verklaart de error, de logica hiervan ontgaat me echter. Waarom protected functies van onderliggende classes alleen van jezelf mogen aanroepen, en niet op andere instanties? Diezelfde logica geldt namelijk niet voor private, aangezien het volgende ook gewoon mag:
code:
1
2
3
4
5
6
7
8
9
10
11
12
class A
{ 
 private:
  void PrivateFunc();
 public:
  void PublicFunc( A *a );
}; 

void A::PublicFunc( A *a )
{
 a->PrivateFunc(); // niks geen gezeur over andere instanties hier
}
Ja maar voor private is het iets anders. Je kunt altijd in de class bij alle private members van een andere instantie van dezelfde class, je zit dan immers in een vertrouwde omgeving. Protected is echter bedoeld om bepaalde members alleen te exposen naar directe descendants van de class. Je kunt er dan dus niet bij via een willekeurige pointer, alleen via this. Dat die private regel het weer opheft zodra je die pointer cast naar een type dat gelijk is aan je eigen klasse is idd jammer maar helaas noodzakelijk. Overigens blijft het een smerige truc; je weet niet of je A * ook een B * is, een dynamic_cast zal dan ook niet altijd lukken en platformen als Java en .Net geven in zo'n geval een exception.

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.


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Heel mooi :D
Dat een class zelf access heeft tot andere instanties is logisch, je zit dan namelijk al in die class. Het is en gesloten cirkeltje dat nooit misbruikt kan worden. Als je die member aan kan passen, dan kan je ook de variabele zelf aanpassen naar eventueel public. Je kan dus niet ergens bij dat iemand anders heeft gemaakt en private declared is.
En als ik behalve een B nu ook een C afleid van A, en beide moeten ze die gedeelde functionaliteit van A kunnen gebruiken op een andere instantie (ongeacht of dat een B of C is). Dan kan dat dus niet, dan moet ik me in B en C allebei beperken tot instanties van zichzelf. Dat is toch een rare beperking?

Het "misbruik" argument zie ik niet zo, als ik per se onder bepaalde afscherming uit wil komen kan dat toch wel (public inline functie aan A.h toevoegen die op een meegegeven instantie die Func aanroept, de reeds genoemde "#define protected public", mogelijkheden te over).

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

JaceTBL schreef op 27 oktober 2004 @ 12:37:
[...]

Doe ze de groeten daar :) (zeg was jij toen niet een keer mee wezen voetballen in Arnhem?)
Zal ik doen (en nee, ik ben nooit wezen voetballen in arnhem. Ik ben sowieso nooit wezen voetballen :+)

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.


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
IJnte schreef op 27 oktober 2004 @ 12:43:
Ik heb zelf ook zitten klooien met classes. Ik heb zelf er veel geleerd van de tutorial op cplusplus.com. Kijk eens even of je hier wat aan hebt. Hier staat ook de reden van protected in een class in.
Ook in deze tutorial staat: "protected members are accessible from members of their same class and friend classes, and also from members of their derived classes."
En wederom geen woord over instanties.

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Als je het zo aan wilt roepen is het misschien toch eigenlijk een public functie? Of anders kan je het via friends doen (in dit geval zorgen friends voor meer encapsulatie, ipv minder. Omdat het andere alternatief 'public' zou zijn. En zijn friends dus niet 'evil') . Of een andere klasse structuur.

Dat #define truckje is wel leuk op zich (is niet de eerste keer dat ik het hoor, heel #coders was er vroeger al fan van....hehe) Maar met een shared library en name mangling werkt het niet. Beschermingen worden ingebouwd om fouten te voorkomen; als je daar bewust omheen werkt met trucks, dan loop je het risico op ernstige bugs later... Waarom beveilig je het dan in de eerste plaats? Maak het public.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ik denk dat veel mensen het even "vergeten", ik zou [rml]Zoijar in "[ c++] mag protected functie niet aanroep..."[/rml] het meest vetrouwen, dat is een quote uit de standard itself :)

(Zie ook hier, mocht je het allemaal nog eens willen nalezen :))

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.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Dat het niet mag is duidelijk volgens C++98.
Waarom het niet mag kan aan het volgende liggen (zoals oysin al zei boven)

Stel ik heb een functie waar ik een A* krijg. Die zit in een library, met een protected member x. Ik wil x veranderen, maar dat kan dus niet.
C++:
1
2
3
4
5
6
7
8
class A {
protected:
int x;
};

void foo(A* theA) {
  // how to set the theA.x ??
}


Dan code is er als volgt omheen:
C++:
1
2
3
4
5
6
7
8
9
10
class B : public A {
public:
   static int& x(A* a) {
      return a->x;   // ill-formed!!!
   }
};

void foo(A* theA) {
   B::x(theA) = 5; // Strange? Would the compiler even be able to find the name in the library?
}


@oisyn: lol ;)

[ Voor 4% gewijzigd door Zoijar op 27-10-2004 13:12 . Reden: pijl ipv punt...pointers... ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

En natuurlijk niet alleen ill-formed omdat je een . gebruikt ipv een -> ;)

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.


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Zoijar schreef op 27 oktober 2004 @ 12:52:
Als je het zo aan wilt roepen is het misschien toch eigenlijk een public functie? Of anders kan je het via friends doen (in dit geval zorgen friends voor meer encapsulatie, ipv minder. Omdat het andere alternatief 'public' zou zijn. En zijn friends dus niet 'evil') . Of een andere klasse structuur.
Uhm, nee het is geen public functie, het moet echt alleen toegankelijk zijn voor.. nou ja wat protected doet, maar dan zonder die beperking van instanties.
Friends vind ik in zoverre evil dat ik nu in feite in A iets moet gaan toevoegen voor B, en mocht ik later nog een B2 en B3 maken dan moet ik daar steeds iets voor in A veranderen. En dat vind ik smerig (en druist hard in tegen het idee dat je mooi clean dingen kunt afleiden zonder dat de je daarvoor in de base class moet rommelen).
Maar met een shared library en name mangling werkt het niet.
Oh maar daar valt wel een mouw aan te passen hoor >:)
Beschermingen worden ingebouwd om fouten te voorkomen; als je daar bewust omheen werkt met trucks, dan loop je het risico op ernstige bugs later... Waarom beveilig je het dan in de eerste plaats? Maak het public.
Mee eens, daarom wil ik het ook protected houden. Ik wil nergens omheen werken met truuks, ook al kan het, ik zie die beveiliging als een guideline voor "van deze zooi wordt je geacht af te blijven" en die is er niet voor niks.

Alleen werd hierboven als argument voor die beperking van protected aangedragen "ja maar anders kun je eromheen truken", terwijl dat natuurlijk altijd wel kan (als je dat zou willen).

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

JaceTBL schreef op 27 oktober 2004 @ 13:10:
Alleen werd hierboven als argument voor die beperking van protected aangedragen "ja maar anders kun je eromheen truken", terwijl dat natuurlijk altijd wel kan (als je dat zou willen).
Tsja, reinterpret_cast is je vriend :) Maar nu kan je er op een volledig type-safe manier omheen werken, dat is vreemd. Er staat niets raars in die code boven, alles op die ene regels na is legaal, ongetruckt C++.

Anyway, het kan dus niet :) Hoe je het verder het best op kan lossen weet ik niet precies, friends, of publics, of van je hele hierarchie afzien...keuzes :)

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Zoijar schreef op 27 oktober 2004 @ 13:03:
Stel ik heb een functie waar ik een A* krijg. Die zit in een library, met een protected member x. Ik wil x veranderen, maar dat kan dus niet.
Dan word je kennelijk geacht die x met rust te laten, dus is het slim om je daar aan te houden :)
Dan code is er als volgt omheen:
Ja maar dat is toch geen argument? Als de C++ standaard rekening met houden met dat soort trickery kun je wel ophouden, als het moet kan ik ook const private members van const instanties van totaal andere classes overschrijven. Zonder warnings.

Wat er in dat voorbeeld staat is gewoon een truuk, een static functie om iets van een ander te exposen.

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Nou ja jammer... ook al vind ik het onlogische bullshit, kennelijk werkt C++ zo, period.

Dus vies eromheen hacken (of alles public maken) dan maar weer :'(

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Verdere rationale ken ik niet... je zou het eens kunnen proberen op te zoeken of te vragen in comp.lang.c++(.moderated) wat de precieze rationale achter deze regel is. Er zitten wel mensen van het standard commitee daar geloof ik. Ik denk dat je mijn voorbeeld voorgeschoteld krijgt, maar het zou kunnen dat er ook nog andere (misschien meer dringende?) redenen zijn.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Hier ook hoor :)

Zoijar's diagram was een heel nette methode om het te laten zien.

De reden voor de semantiek van protected is duidelijk als je kijkt naar de bewaking van invarianten. Stel, je hebt een class A met protected member x. Derived class B0 heeft een invariant 'x is even'; Derived class B1 heeft een invariant 'x is oneven'.

In B0::foo( ) heb je dus de expressie this->x, wat is de invariant daarvan? Simpel, 'is even'. In B1::bar( A* that ) heb je de expressie that->x, wat is de invariant daarvan? Dat weet je dus niet! Je weet niet eens wat voor een x je hebt, misschien is het wel een B2::x. Daarom mag B1::bar dus niet bij that->x

[ Voor 6% gewijzigd door MSalters op 27-10-2004 18:30 ]

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
MSalters schreef op 27 oktober 2004 @ 18:30:
Hier ook hoor :)

Zoijar's diagram was een heel nette methode om het te laten zien.

De reden voor de semantiek van protected is duidelijk als je kijkt naar de bewaking van invarianten. Stel, je hebt een class A met protected member x. Derived class B0 heeft een invariant 'x is even'; Derived class B1 heeft een invariant 'x is oneven'.

In B0::foo( ) heb je dus de expressie this->x, wat is de invariant daarvan? Simpel, 'is even'. In B1::bar( A* that ) heb je de expressie that->x, wat is de invariant daarvan? Dat weet je dus niet! Je weet niet eens wat voor een x je hebt, misschien is het wel een B2::x. Daarom mag B1::bar dus niet bij that->x
Ben niet bekend met de term 'invariant' in deze context; maar ik krijg een beetje ongemakkelijk gevoel bij dit voorbeeld. Is het niet gewoon fout en had er in deze situatie helemaal geen common x in A moeten zitten, maar had je B0 en B1 ieder een eigen x moeten geven waar ze allebei hun specifieke ding mee doen?

Ik probeer ff een simpel voorbeeld te verzinnen waarbij wat ik wil m.i. zou moeten mogen, maar nu niet mag.

(edit) hier ff een laf voorbeeld:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Kunstwerk
{
 protected:
  virtual Image* GetFoto() = 0;
};

class Beeldhouwwerk : public Kunstwerk
{
 ... o.a. implementatie van Image* GetFoto() ...
};

class Schilderij : public Kunstwerk
{
 protected:
  Image* GetFoto();
  void CombineerMetAnderKunstwerk( Kunstwerk *ander );
};

void Schilderij::CombineerMetAnderKunstwerk( Kunstwerk *ander )
{
 Image *foto = ander->GetFoto();
 ... verwerk foto van dat andere kunstwerk in dit schilderij ofzoiets ...
}


Dat laatste leek me correct (en niet OO-principes verkrachtend of whatever), maar het mag niet ;(

[ Voor 30% gewijzigd door Jace / TBL op 28-10-2004 10:58 ]


Verwijderd

Laat ik ook eens een duit in het zakje doen! :)
Ik zie precies waarom het niet goed gaat in je voorbeeld, ik weet alleen niet of ik het kan uitleggen..... Private en protected functies hebben met elkaar gemeen dat ze niet 'van buitenaf' kunnen worden aangeroepen. En dat gebeurt nu precies met de binnenkomende pointer. Een ander object (van het type schilderij) probeert in een van zijn functies een protected functie van weer een ander object aan te roepen. En dat mag niet.

Stel nou dat GetFoto() niet pure virtual was in de base class, maar daar gewoon een implementatie zou hebben en schilderij zou die functie niet override hebben. Dan zou schilderij in een willekeurige functie van hemzelf GetFoto() kunnen aanroepen (en hier zit het verschil met private, want dan zou het niet kunnen). Maaaaar 'van buitenaf' dus iets in de trant van picasso.GetFoto() of picasso->GetFoto() zou nooit kunnen. (tenzij in een copy constructor, of zeker dat het hetzelfde type is, wat zeg maar op de vorige pagina van de thread al genoemd is)

Is dit enigszins te begrijpen....? :|

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Verwijderd schreef op 29 oktober 2004 @ 00:10:
Is dit enigszins te begrijpen....? :|
Nee :)
Ook al is GetFoto niet pure virtual of uberhaupt niet virtual, het gaat erom dat een protected functie te gebruiken is vanuit de class en afgeleide classes. In dit geval is zowel this (schilderij) als die *ander een Kuntswerk.

Kijk, ik zou dit logisch vinden:
• private functies = mag je alleen aanroepen vanuit de class zelf
• protected functies = mag je alleen aanroepen vanuit de class zelf en vanuit classes die ervan zijn afgeleid
• public functies = mag je ook van buitenaf aanroepen (overal dus)

Verwijderd

JaceTBL schreef op 29 oktober 2004 @ 10:36:
[...]

Nee :)
Ook al is GetFoto niet pure virtual of uberhaupt niet virtual, het gaat erom dat een protected functie te gebruiken is vanuit de class en afgeleide classes. In dit geval is zowel this (schilderij) als die *ander een Kuntswerk.

Kijk, ik zou dit logisch vinden:
• private functies = mag je alleen aanroepen vanuit de class zelf
• protected functies = mag je alleen aanroepen vanuit de class zelf en vanuit classes die ervan zijn afgeleid
• public functies = mag je ook van buitenaf aanroepen (overal dus)
Waar het mis gaat is dat het niet duidelijk is of 'Kunstwerk *ander' van het type schilderij is. er kunnen wel 1000 verschillende classes zijn die allemaal zijn afgeleid van Kunstwerk. Het feit dat twee verschillende classes dezelfde base-class gemeen hebben wil niet zeggen dat ze hetzelfde zijn. Sterker nog, ze zijn absoluut niet hetzelfde en dus mogen ze niet aan elkaars private en protected members en functies komen.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je hebt hier te maken met een verkeerd ontwerp. GetFoto is protected, wat een beetje nutteloos is aangezien je die in een derived zelf moet implementeren, en deze niet vanuit de base aangeroepen wordt (wat de enige reden is om een pure virtual method protected te maken: een derived kan die imlpementeren zodat je die vanuit de base aan kunt roepen). Wat jij echter wilt is een method die door iedereen aangeroepen kan worden om de image op te vragen, en deze moet dus public zijn.

Wat echter ook kan, en dan heb je het min of meer zoals jij het wilt: maak een protected static functie in Kunstwerk die de Image van een willekeurig Kunstwerk retourneert. In die functie roep je dan gewoon simpelweg GetFoto () op het meegegeven object aan.

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.


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Verwijderd schreef op 29 oktober 2004 @ 10:53:
Waar het mis gaat is dat het niet duidelijk is of 'Kunstwerk *ander' van het type schilderij is.
Dat hoeft ook niet, het mag ook een Beeldhouwwerk of nog een ander Kunstwerk zijn.
er kunnen wel 1000 verschillende classes zijn die allemaal zijn afgeleid van Kunstwerk. Het feit dat twee verschillende classes dezelfde base-class gemeen hebben wil niet zeggen dat ze hetzelfde zijn. Sterker nog, ze zijn absoluut niet hetzelfde en dus mogen ze niet aan elkaars private en protected members en functies komen.
Inderdaad, maar ik laat ze dan ook alleen aan elkaars onderdelen zitten die ze gemeen hebben. Ze zijn wel in zoverre hetzelfde dat het allemaal Kunstwerken zijn, en ik heb in de baseclass gedefinieerd dat een Kunstwerk een afbeelding van zichzelf moet kunnen genereren. En ik heb ook gedefinieerd dat afgeleide classes hiervan gebruik mogen maken (protected).

Overigens hou ik het zelfde probleem als GetFoto niet pure virtual was geweest, maar gewoon geïmplementeerd in Kunstwerk en niet overridebaar in afgeleide classes.

[ Voor 5% gewijzigd door Jace / TBL op 29-10-2004 12:16 ]


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
.oisyn schreef op 29 oktober 2004 @ 11:51:
Je hebt hier te maken met een verkeerd ontwerp. GetFoto is protected, wat een beetje nutteloos is aangezien je die in een derived zelf moet implementeren, en deze niet vanuit de base aangeroepen wordt (wat de enige reden is om een pure virtual method protected te maken: een derived kan die imlpementeren zodat je die vanuit de base aan kunt roepen).
Dit was natuurlijk een versimpeld voorbeeld, in de praktijk bevat de baseclass nog meer, waaronder functies die GetFoto gebruiken.
Maar dan nog, wat is er verkeerd aan het idee dat Kunstwerken allemaal iets moeten kunnen, en allemaal op hun eigen manier zonder dat er een default manier is (vandaar pure virtual), en dat ik van die common functionaliteit gebruik maak in een afgeleide class?
Wat jij echter wilt is een method die door iedereen aangeroepen kan worden om de image op te vragen, en deze moet dus public zijn.
Nee, ik wil een method die alleen door Kunstwerken (*) kunnen worden aangeroepen. Niet van buitenaf.

(*) waarbij ik Schilderijen, Beeldhouwwerken en andere van Kunstwerk afgeleide classes in dit geval ook als Kunstwerk beschouw, anders had ik hem private gemaakt ipv public
Wat echter ook kan, en dan heb je het min of meer zoals jij het wilt: maak een protected static functie in Kunstwerk die de Image van een willekeurig Kunstwerk retourneert. In die functie roep je dan gewoon simpelweg GetFoto () op het meegegeven object aan.
Da's wel een aardige ja, vind ik iets frisser dan friends, omdat ik zo niet voor elke nieuwe class die ik afleid van Kunstwerk iets aan de baseclass hoef toe te voegen.
Overigens hoeft ie niet static te zijn (maar liever wel omdat ie toch niks met this te maken heeft).

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

JaceTBL schreef op 27 oktober 2004 @ 13:43:
Nou ja jammer... ook al vind ik het onlogische bullshit, kennelijk werkt C++ zo, period.

Dus vies eromheen hacken (of alles public maken) dan maar weer :'(
Je kunt de base class ook friend maken met de derived class ;)

Maar zoals gezegd is het niet de taal die hier schuldig is maar jouw ontwerp. Die functie hoort gewoon niet protected te zijn als ie door andere classes (of ze nu wel of niet van eigen type zijn of niet) aangeroepen moet worden, dan heb je een public functie.

Professionele website nodig?


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
curry684 schreef op 29 oktober 2004 @ 12:31:
Je kunt de base class ook friend maken met de derived class ;)
Kan... Maar dan moet ik voor alle classes die van Kunstwerk zijn afgeleid (of die ik ooit van Kunstwerk ga afleiden) toevoegen aan die base class, da's toch smerig? Het idee van afleiden is juist dat ik die gedeelde functionaliteit mooi kan gebruiken, zonder daarvoor in de baseclass te hoeven rotzooien.
Maar zoals gezegd is het niet de taal die hier schuldig is maar jouw ontwerp. Die functie hoort gewoon niet protected te zijn als ie door andere classes (of ze nu wel of niet van eigen type zijn of niet) aangeroepen moet worden, dan heb je een public functie.
Nee ik wil geen public functie, public functies mogen ook door de boze buitenwereld worden aangeroepen. Ik wil dat mijn functie alleen door Kunstwerken kan worden gebruikt.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

En dat is dus de crux: je gaat tegen de bron van Object Oriented Programming in door een object te maken dat per definitie reusable code is, en vertikt het vervolgens die code publiek reusable te maken.

Hierbij wel vermeld dat .NET wel doet wat je wilt door 'internal' visibility toe te voegen aan het arsenaal, maar in essentie doe je iets wat simpelweg niet de bedoeling is van object reuse.

Professionele website nodig?


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
curry684 schreef op 29 oktober 2004 @ 13:02:
En dat is dus de crux: je gaat tegen de bron van Object Oriented Programming in door een object te maken dat per definitie reusable code is, en vertikt het vervolgens die code publiek reusable te maken.
Dat is onzin, het is toch volstrekt redelijk om bepaalde functionaliteit van mijn object af te schermen voor de buitenwereld?

Waar dienen protected en private anders voor?

Verwijderd

JaceTBL schreef op 29 oktober 2004 @ 13:38:
Dat is onzin, het is toch volstrekt redelijk om bepaalde functionaliteit van mijn object af te schermen voor de buitenwereld?

Waar dienen protected en private anders voor?
Dat is inderdaad heel redelijk. Helaas (?) kun je in C++ geen stukken functionaliteit afschermen voor slechts bepaalde stukken van de buitenwereld. Je schermt ze af, of niet. En daar dient protected en private voor. Natuurlijk kun je dan wel de afgeschermde stukken toegankelijk maken voor een stuk van die buitenwereld. That's where friends come in :)

Ik krijg het vermoeden dat jij meer wil. Jij wil een aantal stukken functionaliteit (bvb F1, F2 en F3 genoemd) afschermen voor (her)gebruik in klassen A, B, C, etc en wel zodanig dat A alles mag, B mag wel F1 en F3 gebruiken maar niet F2 en C mag dan weer enkel F2 en F3 terwijl D etc. En dat kan niet voor zover ik weet.

Ik weet ook niet helemaal zeker of ik zoiets wel zou willen. Ik schrijf nu toch al enkele jaren software in C++ (niet dat ik daarom meteen C/C++ expert ben, verre van) en ik moet zeggen dat de wens om zo'n dingen te doen nog nooit is bovengekomen bij mij. Ik heb al veel dingen aan C++ vervloekt, maar dit nog net niet ;)

Verwijderd

JaceTBL schreef op 29 oktober 2004 @ 13:38:
Waar dienen protected en private anders voor?
Niet voor wat jij probeert te doen. Ik heb nog es nagedacht over je probleem en dit is eruit gekomen..... ;)
code:
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
class IMage {};

template <class T>
class KunstWerk
{
    T *m_pSource;
public:
    KunstWerk(T *pSource) {m_pSource = pSource;}
    IMage *Photo()
    {
        return m_pSource->GetPhoto();
    }
};

class BaseArt
{
            friend KunstWerk<BaseArt>;
protected:
    virtual IMage * GetPhoto() = 0; 
};

class Schilderij : public BaseArt
{
protected:
    virtual IMage * GetPhoto() { return new IMage(); } 
};

class BeeldHouw : public BaseArt
{
protected:
    virtual IMage * GetPhoto() { return new IMage(); } 
};

int main()
{
    KunstWerk<BaseArt> paint(new Schilderij());
    KunstWerk<BaseArt> sculpt(new BeeldHouw());
    IMage *im_1 = paint.Photo();
    IMage *im_2 = sculpt.Photo();
    return 1;
}


Het idee is dat je alleen met objecten van het type kunstwerk werkt en die instantieert met objecten afgeleidt van het type baseart.

edit:
zat een 'onvolledigheid' in de code :Y)

[ Voor 6% gewijzigd door Verwijderd op 29-10-2004 15:01 ]


  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Verwijderd schreef op 29 oktober 2004 @ 14:46:
Dat is inderdaad heel redelijk. Helaas (?) kun je in C++ geen stukken functionaliteit afschermen voor slechts bepaalde stukken van de buitenwereld. Je schermt ze af, of niet. En daar dient protected en private voor. Natuurlijk kun je dan wel de afgeschermde stukken toegankelijk maken voor een stuk van die buitenwereld. That's where friends come in :)
Protected is toch juist een tussenvorm: je schermt het dan af voor de buitenwereld, maar niet voor classes die van je huidige class afleiden. Dat is nou net het verschil met private.

Dus heb je een class Ding, dan mag een protected functie alleen door Dingen worden gebruikt - in de ruime zin des woords, want classes die afgeleid zijn van Ding zijn zelf ook Dingen.
Ik krijg het vermoeden dat jij meer wil. Jij wil een aantal stukken functionaliteit (bvb F1, F2 en F3 genoemd) afschermen voor (her)gebruik in klassen A, B, C, etc en wel zodanig dat A alles mag, B mag wel F1 en F3 gebruiken maar niet F2 en C mag dan weer enkel F2 en F3 terwijl D etc. En dat kan niet voor zover ik weet.
Nee zo moeilijk wil ik het niet maken :)
Ik heb een class A met een functie F, en ik erf B1 en B1 er vanaf. Ik wil dat B1 en B2 (en eventuele toekomstige classes die ik van A ga afleiden) bij F mogen, maar de buitenwereld niet.

  • Jace / TBL
  • Registratie: Augustus 2001
  • Laatst online: 23-03-2023
Verwijderd schreef op 29 oktober 2004 @ 14:52:
Niet voor wat jij probeert te doen.
Waar dan voor? :)
Ik heb nog es nagedacht over je probleem en dit is eruit gekomen..... ;)
(...)
Het idee is dat je alleen met objecten van het type kunstwerk werkt en die instantieert met objecten afgeleidt van het type baseart.
Maar nu is GetPhoto public, dus alles -ook dingen die geen zak met Kunstwerk te maken hebben- kunnen nu bij die functie. Dat wil ik niet, dan had ik net zo goed in mijn voorbeeld simpelweg die GetFoto public kunnen maken :)

Met die templates wordt het er allemaal ook niet frisser op imho, de voorbeeldsituatie die ik schets is toch niet zó exotisch? ;(

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 12-05 22:23

curry684

left part of the evil twins

Hij's wel exotisch :)

Zal ik meteen een voorbeeld geven waarom jouw voorgestelde protected-gedrag zwaar ongewenst is, namelijk met de archetype thread-implementatie:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
class Thread 
{
public:
  Thread();
  void Start();
  void Stop();
  void Wait();
  ...

protected:
  virtual int Execute() = 0;
};

Volgens jouw logica mag ik hiermee een class SmtpServerThread en HttpServerWorkerThread schrijven, en vervolgens mag iedere andere thread in het programma zomaar inline die threads gaan uitvoeren door direct Execute aan te roepen ipv via de gedefinieerde interface van Start/Stop/Wait? Want dat stel je nu wel: iedere Thread-derivant mag rechtstreeks de protected Execute van een willekeurige andere Thread-derivant benaderen volgens jou :) Ik hoef hopelijk niet uit te leggen dat dat pas echt ongewenst gedrag is :P

Professionele website nodig?


Verwijderd

Antwoord:
Ik heb een class A met een functie F, en ik erf B1 en B1 er vanaf. Ik wil dat B1 en B2 (en eventuele toekomstige classes die ik van A ga afleiden) bij F mogen, maar de buitenwereld niet.
Maar nu is GetPhoto public, dus alles -ook dingen die geen zak met Kunstwerk te maken hebben- kunnen nu bij die functie. Dat wil ik niet, dan had ik net zo goed in mijn voorbeeld simpelweg die GetFoto public kunnen maken :)
Met alle respect: dat slaat nergens op. Geen enkel ander object dan Kunstwerk heeft toegang tot die functie. Je hebt toegang tot Photo() en hoewel dat vanwege de implementatie erop lijkt dat je daardoor ook toegang het tot GetPhoto() is dat toch echt niet zo! (probeer je deze structuur voor te stellen met implementaties die wat meer inhoud hebben, daarnaast is een SetFunctie() misschien ook wel een beter voorbeeld dan een GetFunctie())
Met die templates wordt het er allemaal ook niet frisser op imho, de voorbeeldsituatie die ik schets is toch niet zó exotisch? ;(
Helaas moet ik je meedelen dat templates veel zijn, maar exotisch niet, ze worden vollop gebruikt!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 29 oktober 2004 @ 14:52:
[...]

Niet voor wat jij probeert te doen. Ik heb nog es nagedacht over je probleem en dit is eruit gekomen..... ;)
[..code..]

Het idee is dat je alleen met objecten van het type kunstwerk werkt en die instantieert met objecten afgeleidt van het type baseart.

edit:
zat een 'onvolledigheid' in de code :Y)
Beetje rare oplossing, ik zou het zo doen (wat ik al eerder zei):

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
28
class Kunstwerk
{
protected:
    virtual Image* GetFoto () = 0;

    static Image * GetFoto (Kunstwerk * k)
    {
        return k->GetFoto ();
    }
};

class Beeldhouwwerk : public Kunstwerk
{
    /* ... o.a. implementatie van Image* GetFoto() ... */
};

class Schilderij : public Kunstwerk
{
protected:
    Image* GetFoto();
    void CombineerMetAnderKunstwerk( Kunstwerk *ander );
};

void Schilderij::CombineerMetAnderKunstwerk( Kunstwerk *ander )
{
    Image *foto = GetFoto (ander);
    /*... verwerk foto van dat andere kunstwerk in dit schilderij ofzoiets ...*/
}


GetFoto mag nog steeds alleen maar aangeroepen worden van derived classes van Kunstwerk, maar nu is het mogelijk om in een derived de foto van een andere instance van Kunstwerk op te vragen. En dat dus allemaal zonder gepruts met friend.

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.


Verwijderd

.oisyn schreef op 29 oktober 2004 @ 15:41:
[...]

Beetje rare oplossing, ik zou het zo doen (wat ik al eerder zei):

[...code...]

GetFoto mag nog steeds alleen maar aangeroepen worden van derived classes van Kunstwerk, maar nu is het mogelijk om in een derived de foto van een andere instance van Kunstwerk op te vragen. En dat dus allemaal zonder gepruts met friend.
Dat is een kwestie van smaak denk ik dan. Persoonlijk hou ik niet van 'gepruts' met static functies......

edit:
typo

[ Voor 4% gewijzigd door Verwijderd op 29-10-2004 15:46 ]


Verwijderd

JaceTBL schreef op 29 oktober 2004 @ 15:23:
Nee zo moeilijk wil ik het niet maken :)
Ik heb een class A met een functie F, en ik erf B1 en B2 er vanaf. Ik wil dat B1 en B2 (en eventuele toekomstige classes die ik van A ga afleiden) bij F mogen, maar de buitenwereld niet.
Ik zie je probleem. Het probleem is dat de buitenwereld niet is wat jij wil :P
Als je in B1 een functie implementeert die een object van type A als parameter meekrijgt (one way or the other) dan is de implementatie van die functie voor dat object de buitenwereld, terwijl jij wil dat het dat niet zou zijn want immers is die functie een stuk van de API van B1 en een B1 is ook een A (simpel gezegd).

Ik vind het een beetje vreemd dat je dat wil. Het gedrag zoals het nu is vind ik best logisch, maar dat kan aan mij liggen. Anyway: de oplossing hiervoor heeft .oisyn al aangegeven: protected static (hulp)functie in je A duwen...

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

Verwijderd schreef op 29 oktober 2004 @ 15:45:
Dat is een kwestie van smaak denk ik dan. Persoonlijk hou ik niet van 'gepruts' met static functies......
Jouw oplossing doet niet wat de TS vraagt, bovendien breekt het z'n hele inheritance tree, want waarom is een Kunstwerk<Bla1> totaal ongerelateerd aan een Kunstwerk<Bla2>? Het zijn immers beide kunstwerken. Overigens is die template parameter nou niet echt nodig, je gebruikt voor beide BaseArt als template parameter, kun je net zo goed een gewone klasse maken ipv een template

[ Voor 17% gewijzigd door .oisyn op 29-10-2004 16:09 ]

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.


Verwijderd

.oisyn schreef op 29 oktober 2004 @ 16:07:
Jouw oplossing doet niet wat de TS vraagt, bovendien breekt het z'n hele inheritance tree, want waarom is een Kunstwerk<Bla1> totaal ongerelateerd aan een Kunstwerk<Bla2>? Het zijn immers beide kunstwerken.
Onzin. De onderlinge structuur tussen schilderij en beeldhouw en baseart zijn precies hetzelfde als hij voor ogen had.
Overigens is die template parameter nou niet echt nodig, je gebruikt voor beide BaseArt als template parameter, kun je net zo goed een gewone klasse maken ipv een template
Ja, duh! In dit simpele geval ja! Probeer een beetje je fantasie te gebruiken! Zodra de objecten gecompliceerder worden zul je daar niet mee wegkomen. Dan zul je ongetwijfeld een Kunstwerk<Schilderij> of Kunstwerk<Beeldhouw> moeten instantieren.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 00:13

.oisyn

Moderator Devschuur®

Demotivational Speaker

En voor het gemak draai je maar even om het eerste zinnetje van mijn post heen?

Maar goed, ik zie nog altijd niet het nut van de template in deze. Waarom zou je een template maken die een functie wrapped die je ook gewoon normaal aan zou kunnen roepen? Het nut van protected is nu helemaal weg: de functie is namelijk niet protected, iedereen kan hem aanroepen door simpelweg een Kunstwerk<Baseart> te creëren. Je kunt de template (met alle overhead van dien) dus net zo goed helemaal weglaten en gewoon de getFoto () public maken, dan kan óók iedereen 'm aanroepen

Bovendien hoef je niet te schreeuwen, ik hoor je vanaf hier ook wel

[ Voor 84% gewijzigd door .oisyn op 31-10-2004 01:22 ]

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.


  • Knorrend_varken
  • Registratie: Juni 2000
  • Laatst online: 19-05 15:33
En als je nu in plaats van public inheritance, gebruik maakt van protected inheritance, of begrijp ik het probleem niet helemaal goed?

Dus in je base class die methode public maken dan word door protected of private inheritance dat ding weer onzichtbaar voor instanties van afgeleide classes.

[ Voor 55% gewijzigd door Knorrend_varken op 31-10-2004 02:07 ]


Verwijderd

.oisyn schreef op 31 oktober 2004 @ 01:14:
[nohtml]En voor het gemak draai je maar even om het eerste zinnetje van mijn post heen?
Ik weet niet precies wat je bedoelt.... Bedoel je de 'CombineerMetAnderKunstwerk' functie waar hij het eerder over had? Die heb ik er idd niet bij gezet, maar meer omdat het me duidelijk lijkt dat dat nu geen probleem meer zal zijn.
Maar goed, ik zie nog altijd niet het nut van de template in deze. Waarom zou je een template maken die een functie wrapped die je ook gewoon normaal aan zou kunnen roepen? Het nut van protected is nu helemaal weg: de functie is namelijk niet protected, iedereen kan hem aanroepen door simpelweg een Kunstwerk<Baseart> te creëren.
Dit is gewoon pertinent niet waar. Als je een object van het type baseart (of afgeleiden daarvan) instantieert kun je absoluut niet de GetPhoto() functie aanroepen. Alleen kunstwerk heeft beschikking over die functie. In de implementatie zoals die nu is komt dat op hetzelfde neer, dat ben ik met je eens. Maar kunstwerk zou misschien nog wel veel meer met de IMage* kunnen doen voordat ie 'm returnt.
Je kunt de template (met alle overhead van dien) dus net zo goed helemaal weglaten en gewoon de getFoto () public maken, dan kan óók iedereen 'm aanroepen
Dat vind ik ook verreweg de beste optie. Maar daar ging het nu toch niet over?
Bovendien hoef je niet te schreeuwen, ik hoor je vanaf hier ook wel
Je hebt gelijk. Het zal niet meer gebeuren.

  • flowerp
  • Registratie: September 2003
  • Laatst online: 04-02 02:01
Verwijderd schreef op 31 oktober 2004 @ 11:39:

Dit is gewoon pertinent niet waar. Als je een object van het type baseart (of afgeleiden daarvan) instantieert kun je absoluut niet de GetPhoto() functie aanroepen. Alleen kunstwerk heeft beschikking over die functie. In de implementatie zoals die nu is komt dat op hetzelfde neer, dat ben ik met je eens. Maar kunstwerk zou misschien nog wel veel meer met de IMage* kunnen doen voordat ie 'm returnt.
Maar wat jij nu gedaan hebt is een publieke 'proxy' class geschreven die de GetPhoto() mag aanroepen. Het probleem is nu alleen verplaatst. Hoe zorg je er nu voor dat BeeldHouw GetPhoto() van Schilderij mag aanroepen maar iemand anders niet?

It's shocking to find how many people do not believe they can learn, and how many more believe learning to be difficult.


Verwijderd

flowerp schreef op 31 oktober 2004 @ 15:09:
Maar wat jij nu gedaan hebt is een publieke 'proxy' class geschreven die de GetPhoto() mag aanroepen. Het probleem is nu alleen verplaatst. Hoe zorg je er nu voor dat BeeldHouw GetPhoto() van Schilderij mag aanroepen maar iemand anders niet?
Dat moet je dus niet proberen. Het idee hiervan is dat je alleen maar met KunstWerk<> objecten werkt.

Verwijderd

Verwijderd schreef op 01 november 2004 @ 09:03:
[...]

Dat moet je dus niet proberen. Het idee hiervan is dat je alleen maar met KunstWerk<> objecten werkt.
Dit helpt niets maar maakt het wel ingewikkelder. Eerder zou ik proberen een publieke functie alleen vanuit derived classes aan te roepen.

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Verwijderd schreef op 29 oktober 2004 @ 14:46:
[...]

Dat is inderdaad heel redelijk. Helaas (?) kun je in C++ geen stukken functionaliteit afschermen voor slechts bepaalde stukken van de buitenwereld. Je schermt ze af, of niet. En daar dient protected en private voor. Natuurlijk kun je dan wel de afgeschermde stukken toegankelijk maken voor een stuk van die buitenwereld. That's where friends come in :)

Ik krijg het vermoeden dat jij meer wil. Jij wil een aantal stukken functionaliteit (bvb F1, F2 en F3 genoemd) afschermen voor (her)gebruik in klassen A, B, C, etc en wel zodanig dat A alles mag, B mag wel F1 en F3 gebruiken maar niet F2 en C mag dan weer enkel F2 en F3 terwijl D etc. En dat kan niet voor zover ik weet.
Het kan wel indirect. Definieer een nested class interface_for_A met alleen inline methods, die de gewenste interface aanbied. Deze interface is volledig private, maar maakt A een friend. Als A dan iets gedaan wil hebben, gebruikt A daarvoor de interface_for_A class. Wil je standaard groepen F1, F2, F3 hebben dan is dat geen probleem - je interface_for_A inherit simpelweg van een of meer van deze groepen. Ook deze inheritance is dan private.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Verwijderd

MSalters schreef op 01 november 2004 @ 21:46:
Het kan wel indirect. Definieer een nested class interface_for_A met alleen inline methods, die de gewenste interface aanbied. Deze interface is volledig private, maar maakt A een friend. Als A dan iets gedaan wil hebben, gebruikt A daarvoor de interface_for_A class. Wil je standaard groepen F1, F2, F3 hebben dan is dat geen probleem - je interface_for_A inherit simpelweg van een of meer van deze groepen. Ook deze inheritance is dan private.
Creatief. Daar was ik nog niet opgekomen :)
Maar of je zo'n code wil gaan schrijven - en vooral onderhouden en uitbreiden - is maar de vraag ;)
Pagina: 1