I have an abstract class:
public abstract class ExampleBase : IExampleBase
{
protected ExampleBase()
{
this.SetupData();
}
protected abstract Dictionary<int, Adress> RelevantData { get; set; }
protected abstract void SetupData();
public void ProcessData()
{
// use RelevantData
}
}
And a derived class:
public class Example : ExampleBase
{
public Example()
{
}
protected override void SetupData()
{
this.RelevantData = new Dictionary<int, Adress>
{ 1, new Adress { ... } },
{ 2, new Adress { ... } }
}
}
In the base class, ReSharper tells me
Virtual member call in constructor
I understand that it's dangerous to call the method because of the execution order.. but how can I resolve this issue?
Context: I want to set up data in each derived class which will then be processed in the base class. I wanted to call the SetupData()
method in the base class since it's the same in every derived class.
Derived class:
Base class:
You can call a virtual function in a constructor, but be careful. It may not do what you expect. In a constructor, the virtual call mechanism is disabled because overriding from derived classes hasn't yet happened. Objects are constructed from the base up, “base before derived”.
So, Don't invoke virtual functions from constructors or destructors that attempts to call into the object under construction or destruction, Because the order of construction starts from base to derived and the order of destructors starts from derived to base class.
Calling virtual functions in constructors makes your code extremely sensitive to the implementation details in derived classes. You can't control what derived classes do. Code that calls virtual functions in constructors is very brittle.
Similarly, it is permissible to call a virtual function from a constructor or destructor of a class that has the final class-virt-specifier, as in this example. struct A { A(); virtual void f(); }; struct B final : A { B() : A() { f(); // Okay } void f() override; };
You don't. You accept the fact this is dangerous, and (try to) prevent this. This is a design flaw!
You could prevent this for example by moving the call to the highest level class, or make every class responsible for it's own, thus removing the unsafe part of the method call. Then you don't need another class (a base class) to take responsibility for its deriving classes.
If that isn't possible. Make very clear using comments or any other method available that the developer should take this problem into account when updating the code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With