I have a situation similar to below (code is NOT exact, just to get my point across). When I call D.A() I expect the word "Desc" to be printed, but instead "Base" is printed.
class Base {
public:
void A() { B(); }
virtual void B() { cout << "Base"; }
}
class Descendant : public Base {
public:
virtual void B() overriden { cout << "Desc"; }
}
main () {
Descendant D;
D.A();
}
There must be something conceptual I'm missing here. Should D.A() cause "Desc" to be printed? If not, why?
There is an important error in the question. The method A is in fact the constructor of the Base class. And it makes sense that the constructor can't call any methods (even virtual) of derived classes since those derived classes don't exist yet.
When A is a non-ctor, it works as expected.
Related
Consider:
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo()\n"; };
};
class Derived : public Base
{
public:
void foo() override
{
std::cout << "Derived::foo()\n";
Base::foo();
}
};
int main()
{
Derived obj;
obj.foo();
return 0;
}
This is my code. Why can I call Base::foo() in the Derived class if I already redefined it in Derived class. Why doesn't the compiler delete Base::foo in class Derived after redefine?
"why compiler doesn't delete Base::foo in class Derived after redefine"
Because that isn't what virtual and override do. When you provide an override to a base class function, you do not replace it. You are defining a new version for that function. The base class's implementation continues to exist and to be accessible.
Consider the following code. Someone can still use a Base object, and the behaviour should not be changed because Derived exists. The output for base_obj.foo() should continue to be "Base::foo()" regardless of the existance of Derived. :
#include <iostream>
class Base
{
public:
virtual void foo() { std::cout << "Base::foo()\n"; }
};
class Derived : public Base
{
public:
void foo() override { std::cout << "Derived::foo()\n"; }
};
int main()
{
Derived obj;
obj.foo();
Base base_obj;
base_obj.foo();
return 0;
}
Also consider that multiple classes can derive from Base. I could add a class MyClass : public Base with its own version of foo(), and it should not interfere with how Base or Derived objects behave.
If overriding a member function would cause the base member function to be entirely replaced or removed, it becomes nearly impossible to reason about code without reading carefully every class that derives from it. And unless your IDE provides tools for that, it implies reading all of the code base. It would make it C++ code that uses polymorphism extremely difficult to understand.
What I am looking for is a way for a Base class detect that the Derived class was not fully constructed. There is some logic in the Base destructor that I only want executed if the Derived class was fully constructed. I don't want to modify the implementations of Derived at all. I could modify Derived with a flag that gets set at the end of the destructor, but I was hoping for some trick that does this automatically.
class Base {
public:
~Base() {
if (FullyConstructed()) {cout << "fatal program bug"; abort();}
}
};
class Derived : public Base {
public:
Derived()
{
if (Something()) throw std::runtime_error("oh oh");
}
~Derived() { }
};
main()
{
Derived d;
}
When this runs, Base gets constructed, Derived does not get constructed fully because it throws, then immediate ~Base gets called. Because ~Derived is not called, ~Base will call abort.
How do I implement FullyConstructed() in the Base class? Is there a way to detect that the vtable for Derived wasn't constructed?
Well you could build your own way such as:
class Base
{
protected:
bool DerivedIsFullyConstructed;
public:
Base() : DerivedIsFullyConstructed(false)
{
}
~Base()
{
if (DerivedIsFullyConstructed)
{
// whatever you want
}
}
};
class Derived : public Base
{
public:
Derived()
{
// ... stuff
DerivedIsFullyConstructed = true;
}
};
But if I were to see such a thing in practice it would make me want to review the design to see if there's a better way.
A very similar question was asked here:
C++: Overriding a protected method which is called by another method
However, I would like to know how to override a callback function in a Base class so that another method can call the derived class's callback from the constructor rather than the Base class's callback.
I've given an example below:
#include <iostream>
class Base {
protected:
virtual void callback() {
std::cout << "Base" << std::endl;
}
public:
Base() {
callback();
}
};
class Derived : Base {
protected:
void callback() override {
std::cout << "Derived" << std::endl;
}
public:
// Use Base's constructor to call print
Derived() : Base() { }
};
int main() {
Base B;
Derived D;
return 0;
}
The output is:
Base
Base
but I would like the output to be:
Base
Derived
This cannot be done. You can see the explanation in this post.
The object is constructed from base - up. The base class gets constructed first and then the members of the derived class extend / override the base class. So when the base constructor is running, the members of the derived class don't exist yet, so you cannot call them.
Not sure what you need this for, but you can just call the same method again from the derived class and you should see the output of both calls (from base and from derived).
The following code is based on the example on page 298 of C++ Templates: the Complete Guide. I removed the parts not relevant to my question.
class Virtual {
public:
virtual void foo() {
}
};
class Base : private Virtual {
public:
void foo() {
std::cout << "Base::foo()" << '\n';
}
};
class Derived : public Base {
public:
void foo() {
std::cout << "Derived::foo()" << '\n';
}
};
int main()
{
Base *p = new Derived;
p->foo(); // calls Derived::foo()
}
I do not understand how the call p->foo() ends up calling Derived::foo. More concretely, the static type of p is Base*. Base::foo is non-virtual. Now, Base privately inherits from 'Virtual', which has its own foo and it looks as if Base::foo somehow gets the virtual specifier from Virtual::foo. What is actually going on here?
The virtualness of foo is inherited from the base class Virtual.
In fact, writing virtual in Derived::foo will be superfluous and many developers will omit it. You cannot undo virtualness once you've marked that function as virtual in a base class.
You can force a call of Base::foo by writing p->Base::foo(); but that's an ugly contrivance.
Sample code
#include <iostream>
using namespace std;
class Base
{
public:
virtual void Func()
{
cout << "\nIn base func";
}
};
class Derived : public Base
{
public:
void Func()
{
cout << "\nIn derived";
}
};
class Derived2 : public Derived
{
public:
void Func()
{
cout << "\nIn derived2";
}
};
int main()
{
Base* lnewbase = new Derived2();
lnewbase->Func();
return 0;
}
As an example, in the above code, I do not want Func() of Derived to be inherited (seal in C#) which is why there is no virtual keyword although I am aware that it does not change anything in this case. Is there any way to disallow that function to be inherited while making sure it remains a public method?
No; C++ has no equivalent to C#'s sealed modifier.
There is nothing you can do.
Once you make a function in a base class virtual, there's nothing that can be done to get rid of that aspect of it. I can only think of a few things to almost get around it:
Don't make it virtual;
Make a new, public, non-virtual function in Derived that does what you need.
However, in either case, Derived2 will still be able to make its own version of Func(), which will give you the same problem.