<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[virtuelle Funktionen implementieren]]></title><description><![CDATA[<p>Huhu.</p>
<p>Ich habe mal aus Spaß virtuelle Funktionen selbst implementiert. Allerdings habe ich gerade keine Idee, wie man beliebige Funktionssignaturen unterstützen kann. Am besten seht ihr euch einfach direkt meinen Ansatz an.</p>
<pre><code class="language-cpp">#ifndef VIRTUAL_HPP
#define VIRTUAL_HPP

#define VIRTUAL_OBJECT public virtual_base
#define VIRTUAL_INIT(func) register_virtual(#func, &amp;virtual_##func##_wrapper);
#define VIRTUAL_DESTRUCTOR_INIT(type) register_virtual(&quot;virtual_destructor_function&quot;, &amp;type::virtual_destructor_function);
#define VIRTUAL_DELETE(obj) (obj)-&gt;invoke(&quot;virtual_destructor_function&quot;);
#define VIRTUAL_INVOKE(obj, func) (obj)-&gt;invoke(#func);

#define VIRTUAL_FUNCTION(func, type)                            \
	static void virtual_##func##_wrapper(virtual_base* obj) \
	{                                                       \
		static_cast&lt;type*&gt;(obj)-&gt;func();                \
	}

#define VIRTUAL_EMPTY_DESTRUCTOR(type)                             \
	static void virtual_destructor_function(virtual_base* obj) \
	{                                                          \
		delete static_cast&lt;type*&gt;(obj);                    \
	}                                                          \
		                                                   \
	~type() {}

#define VIRTUAL_DESTRUCTOR_BEGIN(type)                             \
	static void virtual_destructor_function(virtual_base* obj) \
	{                                                          \
		delete static_cast&lt;type*&gt;(obj);                    \
	}                                                          \
	                                                           \
	~type()                                                    \
	{

#define VIRTUAL_DESTRUCTOR_END \
	}

#include &lt;map&gt;

class virtual_base
{
	std::map&lt;std::string, void (*) (virtual_base*)&gt; vtable;

protected:
	VIRTUAL_EMPTY_DESTRUCTOR(virtual_base)

	virtual_base()
	{
		VIRTUAL_DESTRUCTOR_INIT(virtual_base)
	}

	void register_virtual(const std::string&amp; funcname, void (*function) (virtual_base*))
	{
		vtable[funcname] = function;
	}

public:
	void invoke(const std::string&amp; funcname)
	{
		vtable.find(funcname)-&gt;second(this);
	}
};

#endif // VIRTUAL_HPP
</code></pre>
<p>Verwendet man dann so:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

#include &quot;virtual.hpp&quot;

struct base : VIRTUAL_OBJECT
{
	base()
	{
		VIRTUAL_INIT(say_hello)
		VIRTUAL_DESTRUCTOR_INIT(base)
	}

	void say_hello()
	{
		std::cout &lt;&lt; &quot;Hello, World! base!&quot; &lt;&lt; std::endl;
	}

	VIRTUAL_FUNCTION(say_hello, base)

	VIRTUAL_DESTRUCTOR_BEGIN(base)
	{
		std::cout &lt;&lt; &quot;base::~base()&quot; &lt;&lt; std::endl;
	}
	VIRTUAL_DESTRUCTOR_END
};

struct derived : public base
{
	derived()
	{
		VIRTUAL_INIT(say_hello)
		VIRTUAL_DESTRUCTOR_INIT(derived)
	}

	void say_hello()
	{
		std::cout &lt;&lt; &quot;Hello, World! derived!&quot; &lt;&lt; std::endl;
	}

	VIRTUAL_FUNCTION(say_hello, derived)

	VIRTUAL_DESTRUCTOR_BEGIN(derived)
	{
		std::cout &lt;&lt; &quot;derived::~derived()&quot; &lt;&lt; std::endl;
	}
	VIRTUAL_DESTRUCTOR_END
};

int main()
{
	derived* d = new derived;

	base* b = d;
	VIRTUAL_INVOKE(b, say_hello)
	VIRTUAL_DELETE(b)

	return 0;
}
</code></pre>
<p>Grüße,<br />
PI</p>
]]></description><link>https://www.c-plusplus.net/forum/topic/292732/virtuelle-funktionen-implementieren</link><generator>RSS for Node</generator><lastBuildDate>Sun, 16 Aug 2026 16:36:10 GMT</lastBuildDate><atom:link href="https://www.c-plusplus.net/forum/topic/292732.rss" rel="self" type="application/rss+xml"/><pubDate>Fri, 16 Sep 2011 14:02:37 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Fri, 16 Sep 2011 14:02:37 GMT]]></title><description><![CDATA[<p>Huhu.</p>
<p>Ich habe mal aus Spaß virtuelle Funktionen selbst implementiert. Allerdings habe ich gerade keine Idee, wie man beliebige Funktionssignaturen unterstützen kann. Am besten seht ihr euch einfach direkt meinen Ansatz an.</p>
<pre><code class="language-cpp">#ifndef VIRTUAL_HPP
#define VIRTUAL_HPP

#define VIRTUAL_OBJECT public virtual_base
#define VIRTUAL_INIT(func) register_virtual(#func, &amp;virtual_##func##_wrapper);
#define VIRTUAL_DESTRUCTOR_INIT(type) register_virtual(&quot;virtual_destructor_function&quot;, &amp;type::virtual_destructor_function);
#define VIRTUAL_DELETE(obj) (obj)-&gt;invoke(&quot;virtual_destructor_function&quot;);
#define VIRTUAL_INVOKE(obj, func) (obj)-&gt;invoke(#func);

#define VIRTUAL_FUNCTION(func, type)                            \
	static void virtual_##func##_wrapper(virtual_base* obj) \
	{                                                       \
		static_cast&lt;type*&gt;(obj)-&gt;func();                \
	}

#define VIRTUAL_EMPTY_DESTRUCTOR(type)                             \
	static void virtual_destructor_function(virtual_base* obj) \
	{                                                          \
		delete static_cast&lt;type*&gt;(obj);                    \
	}                                                          \
		                                                   \
	~type() {}

#define VIRTUAL_DESTRUCTOR_BEGIN(type)                             \
	static void virtual_destructor_function(virtual_base* obj) \
	{                                                          \
		delete static_cast&lt;type*&gt;(obj);                    \
	}                                                          \
	                                                           \
	~type()                                                    \
	{

#define VIRTUAL_DESTRUCTOR_END \
	}

#include &lt;map&gt;

class virtual_base
{
	std::map&lt;std::string, void (*) (virtual_base*)&gt; vtable;

protected:
	VIRTUAL_EMPTY_DESTRUCTOR(virtual_base)

	virtual_base()
	{
		VIRTUAL_DESTRUCTOR_INIT(virtual_base)
	}

	void register_virtual(const std::string&amp; funcname, void (*function) (virtual_base*))
	{
		vtable[funcname] = function;
	}

public:
	void invoke(const std::string&amp; funcname)
	{
		vtable.find(funcname)-&gt;second(this);
	}
};

#endif // VIRTUAL_HPP
</code></pre>
<p>Verwendet man dann so:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

#include &quot;virtual.hpp&quot;

struct base : VIRTUAL_OBJECT
{
	base()
	{
		VIRTUAL_INIT(say_hello)
		VIRTUAL_DESTRUCTOR_INIT(base)
	}

	void say_hello()
	{
		std::cout &lt;&lt; &quot;Hello, World! base!&quot; &lt;&lt; std::endl;
	}

	VIRTUAL_FUNCTION(say_hello, base)

	VIRTUAL_DESTRUCTOR_BEGIN(base)
	{
		std::cout &lt;&lt; &quot;base::~base()&quot; &lt;&lt; std::endl;
	}
	VIRTUAL_DESTRUCTOR_END
};

struct derived : public base
{
	derived()
	{
		VIRTUAL_INIT(say_hello)
		VIRTUAL_DESTRUCTOR_INIT(derived)
	}

	void say_hello()
	{
		std::cout &lt;&lt; &quot;Hello, World! derived!&quot; &lt;&lt; std::endl;
	}

	VIRTUAL_FUNCTION(say_hello, derived)

	VIRTUAL_DESTRUCTOR_BEGIN(derived)
	{
		std::cout &lt;&lt; &quot;derived::~derived()&quot; &lt;&lt; std::endl;
	}
	VIRTUAL_DESTRUCTOR_END
};

int main()
{
	derived* d = new derived;

	base* b = d;
	VIRTUAL_INVOKE(b, say_hello)
	VIRTUAL_DELETE(b)

	return 0;
}
</code></pre>
<p>Grüße,<br />
PI</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120200</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120200</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Fri, 16 Sep 2011 14:02:37 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Fri, 16 Sep 2011 16:02:16 GMT]]></title><description><![CDATA[<p>Eine map ist der falsche Ansatz.<br />
Ich habe ein primitives System mal in C geschrieben. Das konnte Vererbung über Copy&amp;Paste und man konnte nicht die Basisklassen Implementierung einer virtuellen Funktion aufrufen...</p>
<p>Das ganze lief über Funktionszeiger als Member der struct. Ein call sah so aus:</p>
<pre><code class="language-cpp">object-&gt;function(object);
</code></pre>
<p>was natürlich etwas dämlich ist, aber für mein Projekt hat das damals gereicht.</p>
<pre><code class="language-cpp">#include&lt;iostream&gt;
#include&lt;cstdlib&gt;
using namespace std;

#define MAKE_THAT(type) type* that=(type*)o
#define THAT void* o

struct Animal {
   void (*make_noise)(THAT);
   void (*destroy)(THAT);
};
void animal_make_noise(THAT) { cout&lt;&lt;&quot;pure virtual function called\n&quot;; exit(-1); }
void animal_destroy(THAT) {
	MAKE_THAT(Animal);
	delete that;
}
Animal* animal_create() {
   Animal* p = new Animal();
   p-&gt;make_noise=animal_make_noise;
   p-&gt;destroy=animal_destroy;
   return p;
}

struct Dog {
   void (*make_noise)(THAT);
   void (*destroy)(THAT);
}; //copy&amp;paste inheritance
void dog_make_noise(THAT) {
	MAKE_THAT(Dog);
   	cout&lt;&lt;&quot;bar bark\n&quot;;
}
void dog_destroy(THAT) {
	MAKE_THAT(Dog);
	delete that;
}
Dog* dog_create() {
   Dog* p=new Dog();
   p-&gt;make_noise = dog_make_noise;
   p-&gt;destroy=dog_destroy;
   return p;
}

struct Cat {
   void (*make_noise)(THAT);
   void (*destroy)(THAT);
}; //copy&amp;paste inheritance
void cat_make_noise(THAT) {
	MAKE_THAT(Cat);
	cout&lt;&lt;&quot;meouw\n&quot;;
}
void cat_destroy(THAT) {
	MAKE_THAT(Cat);
	delete that;
}
Cat* cat_create() {
   Cat* p=new Cat();
   p-&gt;make_noise = cat_make_noise;
   p-&gt;destroy=cat_destroy;
   return p;
}

int main() {
	Animal* a = (Animal*)dog_create();
	a-&gt;make_noise(a);
	a-&gt;destroy(a);

	a=(Animal*)cat_create();
	a-&gt;make_noise(a);
	a-&gt;destroy(a);
}
</code></pre>
<p>So sah das ganze damals etwa aus. Vielleicht ist das ein Ansatz? Auch wenn es sehr limitiert ist...</p>
<p>PS:<br />
Die Objekt Erstellung ging anders. Die ging in etwa so:</p>
<pre><code class="language-cpp">Dog* dog_create(THAT) {
   MAKE_THAT(Dog);
   if(!that) that=new Dog;
   that = animal_create((Animal*)that);
   that-&gt;make_noise = dog_make_noise;
   that-&gt;destroy = dog_destroy;
}
</code></pre>
<p>so dass die ctors gechained waren und man somit die initialisierung von basisklassen korrekt hatte.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120240</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120240</guid><dc:creator><![CDATA[Shade Of Mine]]></dc:creator><pubDate>Fri, 16 Sep 2011 16:02:16 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Sat, 17 Sep 2011 22:37:05 GMT]]></title><description><![CDATA[<p>Dein Code ist aber irgendwie eine C/C++ Mischung <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
<p>Nunja, egal. Die Idee mit den Memberfunktionszeigern sollte genau das sein, was ich brauche. Werde das mal versuchen, danke <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f44d.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--thumbs_up"
      title=":+1:"
      alt="👍"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120624</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120624</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Sat, 17 Sep 2011 22:37:05 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Sun, 18 Sep 2011 07:06:26 GMT]]></title><description><![CDATA[<p>Hi 314159265358979,</p>
<p>hier ist mein C++-Ansatz:</p>
<pre><code class="language-cpp">#include &lt;iostream&gt;

template&lt;typename TObject, typename TVTable&gt;
struct VTableObject{
	VTableObject(TObject&amp; object, const TVTable&amp; vtable) : object(object), vtable(vtable) {}
	TObject&amp; object;
	const TVTable&amp; vtable;
};

class Animal{};

struct AnimalVTable{
	void (*say_hello)(const Animal&amp; animal);
};

static void hello_cat(const Animal&amp; animal);
static void hello_dog(const Animal&amp; animal);
class Cat;
class Dog;
class CatVTable;
class DogVTable;

static CatVTable&amp; cat_vtable_instance(); // als Funktion, da sonst 2 Dateien notwendig
static DogVTable&amp; dog_vtable_instance();

class Cat : public Animal{
public:
	typedef VTableObject&lt;Cat, CatVTable&gt; vtable_object_type;
	typedef VTableObject&lt;const Cat, CatVTable&gt; vtable_const_object_type;

	vtable_object_type vtable_object() { return vtable_object_type(*this, cat_vtable_instance()); }
	vtable_const_object_type vtable_object() const { return vtable_const_object_type(*this, cat_vtable_instance()); }
	void miau() const { std::cout &lt;&lt; &quot;miau&quot; &lt;&lt; std::endl; }
};

class Dog : public Animal{
public:
	typedef VTableObject&lt;Dog, DogVTable&gt; vtable_object_type;
	typedef VTableObject&lt;const Dog, DogVTable&gt; vtable_const_object_type;

	vtable_object_type vtable_object() { return vtable_object_type(*this, dog_vtable_instance()); }
	vtable_const_object_type vtable_object() const { return vtable_const_object_type(*this, dog_vtable_instance()); }
	void wuff() const { std::cout &lt;&lt; &quot;wuff&quot; &lt;&lt; std::endl; }
};

struct CatVTable{
	AnimalVTable animal_v_table;

	VTableObject&lt;Animal, AnimalVTable&gt; cast_to_animal(Cat&amp; cat) const{ return VTableObject&lt;Animal, AnimalVTable&gt;(cat, animal_v_table); }
	VTableObject&lt;const Animal, AnimalVTable&gt; cast_to_animal(const Cat&amp; cat) const{ return VTableObject&lt;const Animal, AnimalVTable&gt;(cat, animal_v_table); }

	CatVTable(){
		animal_v_table.say_hello = &amp;hello_cat;
	}
};

struct DogVTable{
	AnimalVTable animal_v_table;

	VTableObject&lt;Animal, AnimalVTable&gt; cast_to_animal(Dog&amp; dog) const{ return VTableObject&lt;Animal, AnimalVTable&gt;(dog, animal_v_table); }
	VTableObject&lt;const Animal, AnimalVTable&gt; cast_to_animal(const Dog&amp; dog) const{ return VTableObject&lt;const Animal, AnimalVTable&gt;(dog, animal_v_table); }

	DogVTable(){
		animal_v_table.say_hello = &amp;hello_dog;
	}
};

static CatVTable&amp; cat_vtable_instance(){
	static CatVTable cat_vtable;
	return cat_vtable;
}
static DogVTable&amp; dog_vtable_instance(){
	static DogVTable dog_vtable;
	return dog_vtable;
}

static void hello_cat(const Animal&amp; animal){
	static_cast&lt;const Cat&amp;&gt;(animal).miau();
}

static void hello_dog(const Animal&amp; animal){
	static_cast&lt;const Dog&amp;&gt;(animal).wuff();
}

static void say_hello(VTableObject&lt;const Animal, AnimalVTable&gt;&amp; vtable_object){
	(vtable_object.vtable.say_hello)(vtable_object.object);
}

template&lt;typename T, typename T2&gt;
static void say_hello(VTableObject&lt;T, T2&gt;&amp; vto){
	VTableObject&lt;const Animal, AnimalVTable&gt; animal_vto = vto.vtable.cast_to_animal(vto.object);
	say_hello(animal_vto);
}

template&lt;typename T&gt;
static void say_hello(const T&amp; t){
	typename T::vtable_const_object_type vto = t.vtable_object();
	say_hello(vto);
}

int main(){
	Cat cat;
	Dog dog;
	say_hello(cat);
	say_hello(dog);
}
</code></pre>
<p>Ich glaube er ist etwas flexiblerer.<br />
Da sieht man mal, was der Compiler einem an Schreibarbeit abnimmt <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f62e.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--face_with_open_mouth"
      title=":open_mouth:"
      alt="😮"
    /></p>
<p>Gruß,<br />
XSpille</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120693</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120693</guid><dc:creator><![CDATA[XSpille]]></dc:creator><pubDate>Sun, 18 Sep 2011 07:06:26 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Sun, 18 Sep 2011 14:47:49 GMT]]></title><description><![CDATA[<p>Hm, vielleicht habe ich vergessen zu erwähnen, dass mein Ziel ist, dass man die virtuellen Funktionen möglichst ähnlich den echten schreiben kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120843</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120843</guid><dc:creator><![CDATA[314159265358979]]></dc:creator><pubDate>Sun, 18 Sep 2011 14:47:49 GMT</pubDate></item><item><title><![CDATA[Reply to virtuelle Funktionen implementieren on Sun, 18 Sep 2011 15:29:23 GMT]]></title><description><![CDATA[<p>314159265358979 schrieb:</p>
<blockquote>
<p>Hm, vielleicht habe ich vergessen zu erwähnen, dass mein Ziel ist, dass man die virtuellen Funktionen möglichst ähnlich den echten schreiben kann. <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f609.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--winking_face"
      title=";)"
      alt="😉"
    /></p>
</blockquote>
<p>Ich dachte du wolltest die internen Vorgänge mal nachbauen <img
      src="https://www.c-plusplus.net/forum/plugins/nodebb-plugin-emoji/emoji/emoji-one/1f642.png?v=ab1pehoraso"
      class="not-responsive emoji emoji-emoji-one emoji--slightly_smiling_face"
      title=":)"
      alt="🙂"
    /><br />
Und ich vermute, dass es (auch wenn der Standard nichts vorschreibt) i. d. R. vor Optimierungen, etwa so umgesetzt ist.</p>
]]></description><link>https://www.c-plusplus.net/forum/post/2120865</link><guid isPermaLink="true">https://www.c-plusplus.net/forum/post/2120865</guid><dc:creator><![CDATA[XSpille]]></dc:creator><pubDate>Sun, 18 Sep 2011 15:29:23 GMT</pubDate></item></channel></rss>