[SOLVED] What happens when I call a virtual void that is not overwritten?
Let's say my class B derives from A. Class A has a virtual void, but class B doesn't have an override for that. What happens if I take class B and want to call the method?
Answer by Bunny83 · Nov 24, 2017 at 12:19 PM
Well you will just call the method of class A. Virtual methods allow a derived class to override it but it's not necessary. If you create an abstract method it has to be overridden / implemented by a non abstract derived class. Since abstract methods are required to be implemented by child classes you can't actually define any body for an abstract method in the base class unlike virtual methods.
virtual example
public class BaseClass
{
public virtual void MyMethod()
{
Debug.Log("BaseClass: MyMethod type: " + GetType().Name);
}
}
public class Derived1 : BaseClass
{
}
public Derived2 : BaseClass
{
public override MyMethod()
{
Debug.Log("Derived2: MyMethod");
}
}
// [...]
BaseClass C1 = new BaseClass();
C1.MyMethod(); // prints "BaseClass: MyMethod type: BaseClass"
BaseClass C2 = new Derived1();
C2.MyMethod(); // prints "BaseClass: MyMethod type: Derived1"
BaseClass C3 = new Derived2();
C3.MyMethod(); // prints "Derived2: MyMethod"
abstract example
// if a class contains an abstract method the class itself need to be abstract as well
public abstract class BaseClass
{
// abstract methods can't have a method body
public abstract void MyMethod();
}
// this would produce an error as the Derived1 class is not abstract and does not implement the abstract method
//public class Derived1 : BaseClass
//{
//}
public Derived2 : BaseClass
{
public override MyMethod()
{
Debug.Log("Derived2: MyMethod");
}
}
// This is possible. Abstact classes can't be created. A non abstract class that is derived from an abstract class has to implement all not yet implemented abstract methods / properties
public abstract Derived3 : BaseClass
{
}
// Derived2 has already an implementation but just like virtual methods a child class can override such a method
public class Derived2_2 : Derived2
{
public override void MyMethod()
{
Debug.Log("Derived2_2: MyMethod");
}
}
// [...]
// Not possible, will create an error as you can't create an instance of an abstract class
BaseClass C1 = new BaseClass();
BaseClass C2 = new Derived2();
C2.MyMethod(); // prints "Derived2: MyMethod"
// Not possible, again this is an abstract class so you can't create an instance.
//BaseClass C3 = new Derived3();
BaseClass C4 = new Derived2_2();
C2.MyMethod(); // prints "Derived2_2: MyMethod"
Answer by Dray · Nov 24, 2017 at 12:36 PM
The 'virtual' really only tells c# that the function can be overridden.
If it's not and you're calling it, the method from the base class will be called.
Methods can only be overriden if they are virtual or abstract. The difference is that a virtual method has an implementation while an abstract one does not.
And it might be helpful to note that the override keyword is mostly just overcomplication. It's just something extra you always have to write, just because.
In C++ (which is where C# borrows inheritance syntax) there is no overload keyword. If you write virtual in the base class, it's virtual. Every version in a subclass is automatically virtual. You'd never want one version of the function in a subclass to not be virtual -- that would be weird and confusing.
C# add the overrride keyword (why not just re-use the word virtual?) They pretty much thought more options was always better. There's a write up at https://softwareengineering.stackexchange.com/questions/245393/why-was-c-made-with-new-and-virtualoverride-keywords-unlike-java. There really aren't any examples of when leaving out override is a good idea.
That's pretty interestening, thanks for sharing! I guess the performance difference is what gives overrides a real purpose
Actually C++ does have an override specifier (since version 11), however unlike C# it's not necessary. Though it's used exactly the same way as in C#. However the C++ class system works quite different (as it supports multi inheritance).
ps: The override keyword is not just required "just because". It's all about readability and communicating clear intentions. Ins$$anonymous$$d of overriding you can also hide inherited methods. Both cases require the use of an explicit keyword. It's the same with "out" and "ref" when calling a method that has such a parameter. If the ref keyword wasn't required the following could happen which is impossible in actual C#:
void Some$$anonymous$$ethod(ref Vector3 vec)
{
vec.x = 42;
}
// [ ... ]
Vector3 v = new Vector3(1,2,3);
Some$$anonymous$$ethod(v);
if (v.x != 1)
Debug.Log("WTF!");
This of course would not compile. However if the ref keyword could be omitted this code would actually print "WTF!". C# enforces you to call the method like this:
Some$$anonymous$$ethod(ref v);
and now it's clear that Some$$anonymous$$ethod could possibly modify "v"
Worth noting (threw me off the first time I saw it) there ARE several functions in Unity API that take an object reference as a parameter, and modify its contents, WITHOUT using the ref keyword.
e.g. https://docs.unity3d.com/ScriptReference/Renderer.GetPropertyBlock.html (I found another at some point, don't remember where though)
The only clue, in this case, is that the function returns void. Also, this is only possible with reference types (structs, and base types will REQUIRE the ref keyword to work like that)
Is there any disadvantage to declaring a function that takes a reference-type parameter, using the ref keyword for that parameter (even though it's not necessary)? Perhaps I'm too rigid, but I like to define ANY parameter whose contents will be modified, with the ref keyword, so the caller knows it will happen. (Not actually complaining about how unity API does it, it's just how I want to do it.)
Your answer

Follow this Question
Related Questions
Get reference to dynamically added script 1 Answer
Overwritten Interaction Function is not called on Copies and instantiated GameObjects 0 Answers
Building Scripts on each other 1 Answer
Script execution order of child and parent classes - Parent then children??? 1 Answer
Duplicate class name in metadata without implementations in its virtual methods 0 Answers