[C++] virtual functie geklooi

Pagina: 1
Acties:
  • 136 views sinds 30-01-2008
  • Reageer

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Ik heb een klasse met onderandere deze functies...
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class COGLWindow
{

...
...

private:
    bool Create();                  // WM_CREATE

protected:
    virtual bool OnCreate() { return true; }
...
...

};

Implementatie van bool create()
code:
1
2
3
4
5
6
7
8
9
10
11
12
// Create()
// desc: create the window
bool COGLWindow::Create()
{
    hDC = GetDC(hWnd);
    SetupPixelFormat();
    SetupPalette();
    hGLRC = wglCreateContext(hDC);
    wglMakeCurrent(hDC, hGLRC);

    return OnCreate();
}

Je ziet OnCreate wordt aan geroepen...

Nu heb ik deze klasse overgeerft en heb een implementatie gegeven aan bool OnCreate(). (de virtual functie met lege implementatie)

Echter de inhoud van de functie wordt niet uitgevoerd.

Ondanks dat ik de nieuwe klasse zo instantieer:
code:
1
engine = new CEngine("GL Window", FALSE, 800, 600, 16);

engine is dus de nieuwe klasse die ik gemaakt heb op basis van COGLWindow. In mijn bescheiden mening zou dit goed moeten gaan. Maar dat doet het dus niet.

Iemand ideeën wat er fout is in mijn denkwijze of code? Ik kom er zelf namelijk niet meer uit. En ik wil het graag netjes oplossen, want ik wil graag 1 basis klasse die ik kan hergebruiken voor al mijn GL progjes. Als die oncreate werkt kan ik specifieke dingen netjes in de overgeerfde klasse houden.

Bovendien hoef ik dan niet meer om te kijken naar al die GL en Windows initialiseer shit. Dat is dan netjes weggewerkt in die hoofdklasse.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Zou perfect moeten werken voorzover ik het hier kan zien... lijkt erop dat je iets anders verknalt...? :?

Professionele website nodig?


  • Sjonny
  • Registratie: Maart 2001
  • Laatst online: 21:11

Sjonny

Fratser

|:( <- ik zit niet op te letten ... gaat lekker ...


en maar anders van die OnCreate pure virtual, dan wordt je gedwongen om die over te erven.
code:
1
virtual void OnCreate() = 0;

maar dat is verder geen oplossing van je probleem ofcouse..

The problem is in the part of your brain that handles intelligence.


  • RdeTuinman
  • Registratie: Mei 2001
  • Laatst online: 16-08 07:25
Op zondag 07 oktober 2001 21:42 schreef The - DDD het volgende:

Nu heb ik deze klasse overgeerft en heb een implementatie gegeven aan bool OnCreate(). (de virtual functie met lege implementatie)
Begrijp ik het goed dat je dit hebt in CEngine:
code:
1
bool OnCreate() { ;}

Als dat zo is probeer dan:
code:
1
bool OnCreate();

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Dat geeft een compile time error natuurlijk. (heb zelfs even gechecked)...

Ik gebruik hier Visual C++ 6... Misschien een compiler flag die ik moet omzetten?

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 07 oktober 2001 22:17 schreef The - DDD het volgende:
Dat geeft een compile time error natuurlijk. (heb zelfs even gechecked)...

Ik gebruik hier Visual C++ 6... Misschien een compiler flag die ik moet omzetten?
Sowieso RTTI aanzetten in het project (staat default uit).

Maar het gebruik van RTTI functies zonder dat dat aanstaat genereert warnings/errors overigens. Dit kun je op compiletime vantevoren afvangen met:
code:
1
2
3
#ifndef _CPPRTTI
  #error Cannot compile without RTTI data generation
#endif

Professionele website nodig?


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
De constructor van CEngine is zo:
code:
1
2
    CEngine(const char *szName, bool fscreen, int w, int h, int b) : 
            COGLWindow(szName, fscreen, w, h, b) {}

Misschien dat dit niet goed is..

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

wat heeft run time type info hier nou mee te maken :?

Anyway, wordt OnCreate misschien aangeroepen vanuit de constructor van COGLWindow?

Als dat zo is, dan moet je een andere oplossing gaan zoeken, want virtual functies werken nog niet in de constructor :)

In de constructor wordt namelijk de virtual table geinitializeert (waar dus pointers naar de juiste virtual functies instaan). Aangezien de constructor van COGLWindow voor die van CEngine wordt aangeroepen, wijst de virtual table nog naar die van COGLWindow tijdens de constructor van COGLWindow. Pas daarna, dus bij aanroep van de constructor van CEngine, wordt ie goed gezet

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.


  • RdeTuinman
  • Registratie: Mei 2001
  • Laatst online: 16-08 07:25
En laat die bool OnCreate() -functie eens weg in CEngine??

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op zondag 07 oktober 2001 22:21 schreef curry684 het volgende:

[..]

Sowieso RTTI aanzetten in het project (staat default uit).

Maar het gebruik van RTTI functies zonder dat dat aanstaat genereert warnings/errors overigens. Dit kun je op compiletime vantevoren afvangen met:
code:
1
2
3
#ifndef _CPPRTTI
  #error Cannot compile without RTTI data generation
#endif
Waar zet ik die RTTI aan?

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Op zondag 07 oktober 2001 22:26 schreef OiSyN het volgende:
wat heeft run time type info hier nou mee te maken :?

Anyway, wordt OnCreate misschien aangeroepen vanuit de constructor van COGLWindow?

Als dat zo is, dan moet je een andere oplossing gaan zoeken, want virtual functies werken nog niet in de constructor :)

In de constructor wordt namelijk de virtual table geinitializeert (waar dus pointers naar de juiste virtual functies instaan). Aangezien de constructor van COGLWindow voor die van CEngine wordt aangeroepen, wijst de virtual table nog naar die van COGLWindow tijdens de constructor van COGLWindow. Pas daarna, dus bij aanroep van de constructor van CEngine, wordt ie goed gezet
De Create() functie wordt aangeroepen wanneer het bericht WM_CREATE in de windows procedure komt.

In Create zit weer de Oncreate aanroep()..

Echter in de constructor van de basis klasse wordt wel de windows aangemaakt (CreateWindowEx)... Zou het kunnen zijn dat het WM_CREATE bericht aankomt voordat de constructor klaar is? En dat zodoende de boel vernageld wordt?

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op zondag 07 oktober 2001 22:30 schreef The - DDD het volgende:

[..]

De Create() functie wordt aangeroepen wanneer het bericht WM_CREATE in de windows procedure komt.

In Create zit weer de Oncreate aanroep()..

Echter in de constructor van de basis klasse wordt wel de windows aangemaakt (CreateWindowEx)... Zou het kunnen zijn dat het WM_CREATE bericht aankomt voordat de constructor klaar is? En dat zodoende de boel vernageld wordt?
ik vrees van wel... Dit is dan waarschijnlijk ook een van de redenen dat in MFC je eerst een instantie moet contrueren, en daarna pas de create methode moet aanroepen.

dus ik stel voor om het zo te doen:
code:
1
2
CEngine * engine = new CEngine (bla bla bla);
engine->Create (bla bla bla);

offtopic:
.edit: fuck man curry ik herkende je niet eens met je nieuwe icoon :)

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.


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Zou het een oplossing zijn om het als volgt te doen:

De implementatie van de constructor plaatsen in een init methode (voor de veiligheid natuurlijk als const declareren).

De constructor helemaal leeg houden en dan:
code:
1
2
engine = new Cengine;
engine->init("OpenGL Game", FALSE, 800, 600, 16);

De code in de constructor is altijd vast. Daar wordt namelijk het window met GL render context aangemaakt. Dat is het wel zo ongeveer.

Vervolgens kan ik wel in de constructors van de afgeleide klassen andere subsystemen van mijn programma aanmaken... Zoals een particle engines, resource loader etc...

Enige waar ik rekening mee moet houden is dat ik in de constructor geen threads ga starten... maar dat was ik zowiezo al niet van plan....

Wordt nu namelijk zo gedaan, het ingaan van de messageloop start ook alle andere eventueel benodigde rommel.
code:
1
2
3
engine = new Cengine;
engine->init("OpenGL Game", FALSE, 800, 600, 16);
engine->EnterMessageLoop();

Dan ziet mijn winmain er dus zo uit:
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
WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int nCmdShow)
{
    int loopRet;

    if (!COGLWindow::RegisterWindow(hInst))
    {
        MessageBox(NULL, "Failed to register window class", "Error", MB_OK);
        return -1;
    }

    CEngine *engine = NULL;

    try
    {
        engine = new Cengine;
        engine->init("OpenGL Game", FALSE, 800, 600, 16);
        loopRet = engine->EnterMessageLoop();

        delete engine;

        return loopRet;
    }
    catch(char *sz)
    {   
        MessageBox(NULL, sz, 0, 0);
        delete engine;
    }

    return -1;
}

Damn, best wel balen, ik had het zo mooi uitgedacht dat het allemaal netjes zou gaan. Maar als ik het zo als hierboven aangegeven op kan lossen dan is het nog steeds zeer mooi.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Vaag kan bovenstaande bericht niet meer wijzigen want het is inmiddels gewijzigd door een moderator?? Erg weird..

In ieder geval...

Die WinMain is de enige functie in die file... Verder zelfs geen declaraties of wat dan ook. Alleen wat includes voor de engine klasse.

In ieder geval, bedankt voor de input lui... Was wel effe nodig om er even over te kunnen blaten met wat andere personen.

Edit:
Hij werkt nu mooi :)

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

als je het toch zo doet, waarom gebruik je dan nog een pointer?

dan is dit misschien makkelijker:
code:
1
2
3
4
5
CEngine engine;

...

engine.init (bla bla bla);

scheelt je ook weer een delete op het eind :)
Niet dat het echt superveel uitmaakt, maar zo is het natuurlijk wel minder error-prone

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.


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
virtual LRESULT EnterMessageLoop() =0;

Vanwege dat regeltje en nog meer van zulke in mijn hoofd class.

De hoofdclass is een contract. Elke subklasse ervan moet op dezelfde manier te instantieren en aan te roepen zijn.

Zodoende hoef ik in mijn winmain functie alleen maar op dat punt te wijzigen.

Oh ja:

CEngine *engine = NULL;
is inmiddels
COGLWindow *engine = NULL;
geworden...

Alles werkt dus nu moet alles nog volgens contract werken, maar da's een eitje.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 07 oktober 2001 22:26 schreef OiSyN het volgende:
wat heeft run time type info hier nou mee te maken :?
Moest er ineens aan denken, als ik in mijn projecten RTTI uitzet verknallen de smart pointers alles waardoor van virtual functies verkeerde implementaties worden aangeroepen.

Maar inderdaad, had er weinig mee van doen daar ie waarschijnlijk geen smart pointers gebruikt :)

Professionele website nodig?


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 07 oktober 2001 22:26 schreef OiSyN het volgende:
In de constructor wordt namelijk de virtual table geinitializeert (waar dus pointers naar de juiste virtual functies instaan). Aangezien de constructor van COGLWindow voor die van CEngine wordt aangeroepen, wijst de virtual table nog naar die van COGLWindow tijdens de constructor van COGLWindow. Pas daarna, dus bij aanroep van de constructor van CEngine, wordt ie goed gezet
Het is zelfs nog iets erger... Ik had vandeweek een root-class gemaakt (geen ancestors dus) met daarin 2 pure virtual functies. Deze werden in de constructor van deze base-class aangeroepen. Zodra ik echter een afgeleide class ervan instantieerde kreeg ik linker errors op missende implementaties voor die pure virtuals!

Om de help van VS.net hierover te citeren:
Attempting to call a pure virtual function from the constructor or destructor of an abstract base class can cause LNK2001 (unresolved external symbol "symbol"). A pure virtual function has no base class implementation.
Dus zelfs in een root-class kan dit fout gaan...

Professionele website nodig?


  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
is het eigenlijk mogelijk om in C++ te voorkomen dat in een child class een bepaalde functie van de parent overloaded wordt?

Ik riep daarstraks dat ik een functie const wou maken om te voorkomen dat overlaoden hiervan voorkomen zou worden. Maar ja, da's natuurlijk een bullshit uitspraak van mij. :) Oeps :P

Op zich ben ik er al afgestapt want het kan best nuttig zijn als ik mijn init overload om vervolgens eerst de parent functie aan te roepen en dan de rest van mijn zaakjes te doen. (het gaat nu dus over de init methode)

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Hier wat samples om het virtual functie probleempje wat ik dus tegen kwam te illustreren:
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
#include <iostream.h>

class test
{
public:
    void create() { cout << "Create some\n"; oncreate();}

protected:
    virtual void oncreate() { cout << ""The parent class does some more creating\n\n"";}
};

class test2 : public test
{

protected:
    virtual void oncreate() { cout << ""The child class does some more creating\n\n"";}
};


int main()
{
    test * pBaseClass = new test;

    test2 * pInheritedClass = new test2;

    pBaseClass->create();
    pInheritedClass->create();

    return 0;
}

In het volgende voorbeeldje wordt een virtual functie aangeroepen in de constructor. En dat werkt dus niet helemaal goed. Het werkt wel, maar in de child class (test2) constructor wordt dus ijskoud de oncreate implementatie van de parent uitgevoerd.
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
#include <iostream.h>

class test
{
public:
    test() {create(); oncreate();}
    void create() { cout << "Create some\n";}

protected:
    virtual void oncreate() { cout << "\n\n\n";}
};

class test2 : public test
{
public:
    test2():test() {}
    // is hetzelfde als: test2() {}

protected:
    virtual void oncreate() { cout << "Do some more creating\n";}
};


int main()
{
    
    test * pBaseClass = new test;

    test2 * pInheritedClass = new test2;

    return 0;
}

Detail verschil.. In mijn geval werd waarschijnlijk de oncreate functie al aangeroepen voordat de constructor klaar was en dus de virtual function table was bijgewerkt.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op zondag 07 oktober 2001 23:58 schreef The - DDD het volgende:
is het eigenlijk mogelijk om in C++ te voorkomen dat in een child class een bepaalde functie van de parent overloaded wordt?
Private of niet virtual maken (C++ kent geen final keyword of iets dergelijks).

Professionele website nodig?


  • arjenk|IA
  • Registratie: Januari 2000
  • Laatst online: 04-12-2011
De vtable wordt geinitialiseerd tijdens compileren (staat als ik het goed heb zelfs in een read-only CONST segment).

In je constructor wordt de de pointer naar de vtable gebruikt van de class waartoe de constructor behoort. Daarom werken je virtual functies niet zoals je wilt als je begint met aanroepen vanuit de constructor.

RTTI, pure virtual maken maakt allemaal niets uit. Bovenstaande verklaart trouwens ook waarom pure virtual functies de zaak verergeren, als je ze aanroept vanuit de base class (waar ze dus niet in zijn gedefinieerd) krijg je een run-time error.

De enige manier om het op te lossen is dus een virtual init() functie gebruiken. En daarvoor hoef je hem in de base class niet perse pure te maken en hoeft RTTI niet aan te staan.

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op maandag 08 oktober 2001 09:42 schreef arjenk het volgende:
De vtable wordt geinitialiseerd tijdens compileren (staat als ik het goed heb zelfs in een read-only CONST segment).
Dat is nogal platform afhankelijk... over het algemeen is het datasegment gewoon een alias van het codesegment, waardoor je dus gewoon dingen in het codesegment kunt veranderen mbv het datasegment.
RTTI, pure virtual maken maakt allemaal niets uit. Bovenstaande verklaart trouwens ook waarom pure virtual functies de zaak verergeren, als je ze aanroept vanuit de base class (waar ze dus niet in zijn gedefinieerd) krijg je een run-time error.
uiteraard alleen maar een error als de instantie geen subclass van die base class is... maar dat kan ook helemaal niet, je kunt een base class met een of meerdere pure virtual functions immers niet instantieren, dus je hoort nooit een error te krijgen
De enige manier om het op te lossen is dus een virtual init() functie gebruiken. En daarvoor hoef je hem in de base class niet perse pure te maken en hoeft RTTI niet aan te staan.
en dat wist ie inmiddels dus al :z

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

Op maandag 08 oktober 2001 00:07 schreef The - DDD het volgende:
In het volgende voorbeeldje wordt een virtual functie aangeroepen in de constructor. En dat werkt dus niet helemaal goed. Het werkt wel, maar in de child class (test2) constructor wordt dus ijskoud de oncreate implementatie van de parent uitgevoerd.
Dat klopt, en dit is geen fout van de compiler of windows, maar een deel van taalspecificatie van C++

Een constructor is een speciale method om een object van een vooraf bepaald datatype te creeeren. Een constructor creeert dus altijd een object van de opgegeven class. Als je dus in een constructor een virtual method aanroept dan negeert de compiler het virtual keyword, en roept de method aan die bij de class van die constructor hoort.

Het komt er op neer dat de compiler geen methodes van childtype B aanroept als je hem opdraagt een object van parenttype A te maken. Heel logisch eigenlijk.

  • The - DDD
  • Registratie: Januari 2000
  • Laatst online: 03-09 16:40
Als je er zo over denkt dan klopt het inderdaad. In de constructor wordt ook die VF tabel bewerkt. Dus de compiler kan er gewoon niet van uit gaan dat die tabel in een stabiele toestand is (met kloppende functie pointers).

Met als gevolg dat dus de implementatie van de instantierdende klasse wordt uitgevoerd.

Aangezien class test2 een child is van test. En dat dus eerst test en daarna "daarbovenop" het test2 deel geinstantieerd wordt, houdt dit in dat de constructor van test wordt aangeroepen en daarna die van test2.

In de test constructor wordt de virtual functie aangeroepen en vanwege het VF tabel verhaal wordt altijd de implementatie van de functie van de klasse van de uitvoerende constructor uitgevoerd.

Is het nog duidelijk? :P Voor mij wel in ieder geval.

  • whoami
  • Registratie: December 2000
  • Laatst online: 22:09
Op maandag 08 oktober 2001 00:29 schreef curry684 het volgende:

[..]

Private of niet virtual maken (C++ kent geen final keyword of iets dergelijks).
Als je die functie enkel niet virtual maakt, kun je ze toch nog altijd overloaden? Denk dat private maken hier de enige uitkomst is.

https://fgheysels.github.io/


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op maandag 08 oktober 2001 20:33 schreef whoami het volgende:

[..]

Als je die functie enkel niet virtual maakt, kun je ze toch nog altijd overloaden? Denk dat private maken hier de enige uitkomst is.
ja maar erg veel nut heeft dat niet... neem nou het volgende 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
24
25
26
27
28
29
30
31
32
33
class Base
{
public:
    void func ();
    virtual void vfunc ();
};

class Derived : public Base
{
public:
    void func ();
    void vfunc ();
};

int main ()
{
    Base *base1, *base2;
    Derived *der;

    base1 = new Base;
    der = new Derived;
    base2 = der;

    base1->func ();  // Base::func wordt aangeroepen
    base2->func ();  // Base::func
    der->func ();    // Derived::func

    base1->vfunc (); // Base::vfunc
    base2->vfunc (); // Derived::vfunc
    der->vfunc ();   // Derived::vfunc

    return 0;
}

Dus bij het gebruiken van niet virtual functies is het hele nut van overerving weg... bovendien, als func () vanuit een functie in Base wordt uitgevoerd terwijl het een Derived is, dan wordt gewoon Base::func aangeroepen, of ie nou overloaded is of 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.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op maandag 08 oktober 2001 20:53 schreef OiSyN het volgende:
Dus bij het gebruiken van niet virtual functies is het hele nut van overerving weg... bovendien, als func () vanuit een functie in Base wordt uitgevoerd terwijl het een Derived is, dan wordt gewoon Base::func aangeroepen, of ie nou overloaded is of niet
Daar doelde ik op ja :) Overigens is final wel een gemis omdat C++ voorschrijft dat een functie virtual is vanaf het moment dat ie ERGENS in je inheritance tree virtual is.

Dus als je binnen je eigen framework een class A hebt met enkele virtual functies, en daarvan zelf een class B afleidt, mag iedere boerenlul ze in class C afgeleidt van B overloaden. Hier zou final best van pas komen... :Z

En wat betreft die virtual Init-functie: heel leuk ja zo doe ik het normaliter ook, maar het betrof hier m'n exceptionclass, en je wil niet bij iedere throw het volgende moeten doen:
code:
1
2
3
EOutOfMemory    MyException;
MyException.Init(blahdiblah);
throw MyException;

In plaats van:
code:
1
throw MyException(blahdiblah);

Maar ik heb het al lang en breed netjes opgelost zodat de 2e versie werkt, was alleen lullig dat ik er niet op had gerekend bij m'n eerste gedachten... ;(

Professionele website nodig?


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

maar aan de andere kant... C(++) is wel een taal waarin je in principe alles kan doen. Dus als die boerenlul zonodig die functie wilt overriden dan doet ie het maar, als de boel in de soep loopt is het mooi zijn eigen schuld :)

Misschien vanuit het design aspect niet zo mooi, maar over het algemeen hou ik er niet van dat mij restricties worden opgelegt in C++ :)

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: 18:03

.oisyn

Moderator Devschuur®

Demotivational Speaker

Op dinsdag 09 oktober 2001 20:24 schreef curry684 het volgende:

[..]

Maar ik heb het al lang en breed netjes opgelost zodat de 2e versie werkt, was alleen lullig dat ik er niet op had gerekend bij m'n eerste gedachten... ;(
heb je er nog nachtmerries over gehad? ;)

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.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op dinsdag 09 oktober 2001 21:55 schreef OiSyN het volgende:
heb je er nog nachtmerries over gehad? ;)
Enorm :P

(nee niet die ICQ log posten ;) )

Professionele website nodig?


Verwijderd

Op dinsdag 09 oktober 2001 20:24 schreef curry684 het volgende:
Dus als je binnen je eigen framework een class A hebt met enkele virtual functies, en daarvan zelf een class B afleidt, mag iedere boerenlul ze in class C afgeleidt van B overloaden. Hier zou final best van pas komen... :Z
Als de user geen enkele virtual van A mag overloaden, dan werk je in class B met private inheritance. Mag de user maar een enkele virtual niet overloaden dan declareer of overload je die private (dit is meestal een gevolg van slecht design).
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
class A {
public:
  virtual void a();
  virtual void b();
};

class B1 : private A {
};

class B2 : public A {
private:
  A::a;
};

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

.oisyn

Moderator Devschuur®

Demotivational Speaker

persoonlijk vind ik dit:
code:
1
2
class B1 : private A {
};

een slechte oplossing, want dan kan de buitenwereld niet meer zien dat B1 eigenlijk een uitbreiding van A is, en kun je dus ook geen B1 geven waar een A gevraagd wordt, en dat is nou het hele idee van inheritance.

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.


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 04-09 14:38

curry684

left part of the evil twins

Op woensdag 10 oktober 2001 02:16 schreef mietje het volgende:
Als de user geen enkele virtual van A mag overloaden, dan werk je in class B met private inheritance.
En nu operator new in class A overloaden en dan nog een keertje proberen om class B te instantieren.

Error xxxx: Function 'A::operator new' not accessible because class B uses 'private' inheritance

Nog zo'n stomme designfout in C++ imho. ;(

Professionele website nodig?


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

.oisyn

Moderator Devschuur®

Demotivational Speaker

mietje, kijk nou wat je doet, je helpt die arme jongen aan nog meer nachtmerries! :P

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

Op woensdag 10 oktober 2001 02:21 schreef OiSyN het volgende:
persoonlijk vind ik dit:
code:
1
2
class B1 : private A {
};

een slechte oplossing, want dan kan de buitenwereld niet meer zien dat B1 eigenlijk een uitbreiding van A is, en kun je dus ook geen B1 geven waar een A gevraagd wordt, en dat is nou het hele idee van inheritance.
:) In dit geval heb je objecten met een virtual baseclass die een bepaald gedrag van die objecten bestuurt waar de user geen donder mee te maken heeft. Dan moet zo'n object van de baseclass inheriten, maar de user heeft niets met die inheritance te maken, en mag haar ook niet beinvloeden. Dit is de enige valide reden om private inheritance te gebruiken.

<edit>
En je gaat dus zeker geen operator new overloaden in een soort baseclass die je in java een interface zou noemen.
</edit>
Pagina: 1