Why do we need virtual and override?

Ask about ACS, DECORATE, ZScript, or any other scripting questions here!

Moderator: GZDoom Developers

Forum rules
Before asking on how to use a ZDoom feature, read the ZDoom wiki first. If you still don't understand how to use a feature, then ask here.

Why do we need virtual and override?

Postby SuaveSteve » Sun Oct 11, 2020 4:43 pm

I'm struggling to see what the point of virtual and override is when inheritance works without them. Both these snippets do the same thing:

Code: Select allExpand view

class A {

   void doThing() {
        Console.printf("A");
    }

}


class B : A {

   void doThing() {
      Console.printf("B");
      super.doThing();
   }

}



Code: Select allExpand view

class A {

   virtual void doThing() { Console.printf("A"); }

}


class B : A {

   override void doThing() {
      Console.printf("B");
      super.doThing();
   }

}

SuaveSteve
 
Joined: 05 Jul 2014

Re: Why do we need virtual and override?

Postby phantombeta » Sun Oct 11, 2020 4:55 pm

These snippets don't do the same thing.
In the first snippet, you're shadowing the "doThing" function from A in B. Anything calling "doThing" with a pointer of type A will call A's version of doThing, even if the pointer points to an instance of B.
In the second snippet, you're actually overriding A's "doThing" function, and calling doThing with a pointer of type A will call the correct function if overridden.

As an example, try these two snippets:
Code: Select allExpand view
class Foo : Actor {
    override void PostBeginPlay () {
        asd ();
    }

    void asd () {
        Console.Printf ("aaa");
    }
}

class Bar : Foo {
    void asd () {
        Console.Printf ("bbb");
    }
}

Code: Select allExpand view
class Foo : Actor {
    override void PostBeginPlay () {
        asd ();
    }

    virtual void asd () {
        Console.Printf ("aaa");
    }
}

class Bar : Foo {
    override void asd () {
        Console.Printf ("bbb");
    }
}


Spawn "Foo", then spawn "Bar". With the first snippet, you'll get "aaa" with both, while with the second snippet, you'll get "aaa" when spawning Foo and "bbb" when spawning Bar.
User avatar
phantombeta
In the meadow of sinful thoughts, every flower's a perfect one
 
Joined: 02 May 2013
Location: Brazil, South America, Earth, Orion-Cygnus Arm, Milky Way
Discord: phantombeta#2461
Twitch ID: phantombeta_
Github ID: Doom2fan
Operating System: Windows 10/8.1/8/201x 64-bit
OS Test Version: No (Using Stable Public Version)
Graphics Processor: nVidia with Vulkan support

Re: Why do we need virtual and override?

Postby SuaveSteve » Sun Oct 18, 2020 5:04 pm

I see. Am I correct in saying that ZScript went the route of C++ by having functions non-virtual by default instead of Java where they're virtual by default? And how is that useful?
SuaveSteve
 
Joined: 05 Jul 2014

Re: Why do we need virtual and override?

Postby Chris » Sun Oct 18, 2020 7:03 pm

SuaveSteve wrote:I see. Am I correct in saying that ZScript went the route of C++ by having functions non-virtual by default instead of Java where they're virtual by default? And how is that useful?

Less overhead. A non-virtual member function is essentially just a normal function with an implicit 'this' pointer. It's invoked directly. A virtual member function is a function pointer in a vtable, which requires indirect memory accesses (and as minor as a memory access may be, they can very quickly add up, especially if it's hitting "cold" memory that's not in the cpu's cache).
User avatar
Chris
 
Joined: 17 Jul 2003

Re: Why do we need virtual and override?

Postby dpJudas » Sun Oct 18, 2020 8:44 pm

It isn't just the saved memory access. When the function isn't virtual the compiler can inline more functions (*). A virtual function can't be inlined unless the compiler can determine that the object reference cannot possibly be a derived version of the class.

*) The compiler doesn't actually inline any functions right now, but that's besides the point.
dpJudas
 
 
 
Joined: 28 May 2016

Re: Why do we need virtual and override?

Postby Graf Zahl » Mon Oct 19, 2020 12:14 am

Another point is programming safety. A virtual function can be overridden by a child class at will and you lose all control over the program flow because users can hook themselves into code they are not supposed to touch.

It's not as bad as Objective-C, though, where a program can replace any method at run time and wreak havoc. Virtual by default is fundamentally unsafe and mostly found in academic languages that unfortunately found their way into production environments.
User avatar
Graf Zahl
Lead GZDoom+Raze Developer
Lead GZDoom+Raze Developer
 
Joined: 19 Jul 2003
Location: Germany


Return to Scripting

Who is online

Users browsing this forum: No registered users and 0 guests