Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!
Werbeanzeige
C-/C++-Quelltext |
|
1 2 3 4 5 |
template <class T> void CTextelement<T>::SetText(const std::string &newtext) { text = newtext; // "text" ist ein std::string } |
C-/C++-Quelltext |
|
1 |
button1->SetText("Hallo"); |
C-/C++-Quelltext |
|
1 2 3 4 5 |
class basisklasse1 {}; template <class T> class textelement : public T {}; basisklasse1 *p = new textelement<basisklasse1>; |
C-/C++-Quelltext |
|
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 |
// erweitert IUnknown um eine methode (interface) struct Refcounting : public IUnknown // ein basiselement (interface) struct Element : virtual public Refcounting // unabhängiges interface struct Textelement { virtual void SetText(const std::string &) = 0; }; // button-interface struct Button : public Element, public Textelement ////// IMPL // CRefcounting implementiert Refcounting template <class T> class CRefcounting : virtual public Refcounting, public T // CElement implementiert Element template <class T> class CElement : public CRefcounting<T> // das textelement template <class T> class CTextelement : public T // der button class CButton : public CTextelement<CElement<Button> > |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
49: std::string h("hallo"); 50: const std::string *ptr = &h; 51: const void *vptr = ptr; 52: b->SetText(h); mov esi,esp lea eax,[ebp-64h] // addresse des (testweise) lokal angelegten strings holen push eax // und auf den stack pushen. wert ist hier 0x0013fea8 mov ecx,dword ptr [ebp-3Ch] // vtbl add ecx,8 // vtbl mov edx,dword ptr [ebp-3Ch] // vtbl mov eax,dword ptr [edx+8] // vtbl mov edx,dword ptr [eax] // vtbl call edx // vtbl - call |
C-/C++-Quelltext |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
6155: template <class T> 6156: void CTextelement<T>::SetText(const std::string &newtext) 6157: { 6158: text = newtext; mov eax,dword ptr [esp+4] // eax ist immernoch 0x0013fea8 push 0FFFFFFFFh push 0 push eax add ecx,78h call 100014C0 6159: } ret 4 |
Zitat von »"Gotbread"«
wenn jede klasse direkt von ihrem interface erbt, wird die implementation
von den pure-virtual funktionen überschrieben und nicht umgekehrt.
(ka warum)
Quellcode |
|
1 2 3 4 5 |
[refcounting] -> [element] -> [button] | | | DLL interface ____|__________________|______________|_______________ | | | implementation [crefcounting] -> [celement] -> [cbutton] |
C-/C++-Quelltext |
|
1 2 3 4 5 6 |
Button *CWindow::AddButton() { Button *b = new CButton(this); childs.push_back(b); return b; } |
Zitat von »"Gotbread"«
anstatt die implementierten methoden der crefcounting-klasse
zu erben, hat er sich für die abstrakten methoden aus dem interface
entscheiden. das gab natürlich linkerfehler. das zieht sich durch
alles klassen durch.
C-/C++-Quelltext |
|
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 |
// testproj.cpp : Defines the entry point for the console application. // #include <iostream> struct Refcounting { virtual ~Refcounting(){} virtual void Release() = 0; }; struct Element : virtual public Refcounting { virtual void SayHello() = 0; }; struct Dings : public Element { virtual void MachNix() = 0; }; //////////////////////////////////////// class CRefcounting : public virtual Refcounting { public: void Release() { delete this; // böse, aber nützlich } }; class CElement : public Element, public CRefcounting { public: void SayHello() { std::cout << "hello" << std::endl; } }; class CDings : public CElement, public Dings { }; Element *Create() { //return static_cast<Dings *>(new CDings); return new CElement; } int main() { Element *d = Create(); d->SayHello(); d->Release(); std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); std::cin.get(); } |
Quellcode |
|
1 2 3 4 5 6 7 8 9 10 11 12 |
1>Compiling... 1>testproj.cpp 1>testproj.cpp(34) : warning C4250: 'CElement' : inherits 'CRefcounting::CRefcounting::Release' via dominance 1> testproj.cpp(22) : see declaration of 'CRefcounting::Release' 1>testproj.cpp(37) : warning C4250: 'CDings' : inherits 'CRefcounting::CRefcounting::Release' via dominance 1> testproj.cpp(22) : see declaration of 'CRefcounting::Release' 1>testproj.cpp(40) : error C2259: 'CDings' : cannot instantiate abstract class 1> due to following members: 1> 'void Dings::MachNix(void)' : is abstract 1> testproj.cpp(16) : see declaration of 'Dings::MachNix' 1> 'void Element::SayHello(void)' : is abstract 1> testproj.cpp(12) : see declaration of 'Element::SayHello' |
C-/C++-Quelltext |
|
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 |
// testproj.cpp : Defines the entry point for the console application. // #include <iostream> struct Refcounting { virtual ~Refcounting(){} virtual void Release() = 0; }; struct Element : virtual public Refcounting { virtual void SayHello() = 0; }; struct Dings : public virtual Element { virtual void MachNix() = 0; }; //////////////////////////////////////// class CRefcounting : public virtual Refcounting { public: void Release() { delete this; // böse, aber nützlich } }; class CElement : public virtual Element, public CRefcounting { public: void SayHello() { std::cout << "hello" << std::endl; } }; class CDings : public CElement, public Dings { void MachNix() {} }; Element *Create() { //return static_cast<Dings *>(new CDings); return new CDings; } int main() { Element *d = Create(); d->SayHello(); d->Release(); std::cin.clear(); std::cin.ignore(std::cin.rdbuf()->in_avail()); std::cin.get(); } |
Werbeanzeige