This question already has answers here:
What if the virtual destructor defined in derived class, but not the top of hierarchy? C++
(4 answers)
Closed 3 years ago.
I am just trying to understand some concepts of inheritance/polymorphism and tried to inherit a class from std::string as shown below:
#include <iostream>
using namespace std;
class MyClass : public std::string
{
virtual ~MyClass()
{
cout << "Inside Virutal Destructor" << endl;
}
};
int main()
{
string *s = new MyClass();
delete s;
cout << "Program started" << endl; //NEVER REACHES HERE
}
QUESTION: With the above code, I was expecting a call to the virtual destructor at the line delete s but as soon as the program reaches there, the program enters into some undefined state (i.e. doesn't crash, doesn't go forward). Where is the program stuck?
The standard class template std::basic_string does not have a virtual destructor. So the class does not have a pointer to the destructor in the table of virtual function pointers. As a result the virtual destructor of the derived class will not be called.
Consider the following demonstrative program
#include <iostream>
struct A
{
void f() const { std::cout << "A::f()\n"; }
};
struct B : A
{
virtual void f() const { std::cout << "virtual B::f()\n"; }
};
struct C : B
{
void f() const override { std::cout << "virtual C::f()\n"; }
};
int main()
{
C c;
A *ac = &c;
B *bc = &c;
ac->f();
bc->f();
return 0;
}
Its output is
A::f()
virtual C::f()
Class A has a non-virtual function f.
Class B has a virtual function f that hides the non-virtual function of the class A and does not override it.
Class C overrides the virtual function of the class B.
Related
This question already has answers here:
Initialization Order of Class Data Members
(2 answers)
Closed 11 months ago.
This little test program crashes and I'm interested why it does:
#include <iostream>
struct SomeClass {
SomeClass() {
}
virtual ~SomeClass() {
}
void test() {
std::cout << "test" << std::endl;
}
virtual void onInit() {
std::cout << "test" << std::endl;
}
};
struct Base {
Base(SomeClass *ptr) {
ptr->test();
ptr->onInit();
}
};
struct Derived : Base {
SomeClass cls;
Derived() : cls(), Base(&cls) {
}
};
int main(int, const char **) {
Derived test;
}
Why can't I call the virtual function onInit from the base class? Isn't that fully initialized when I use cls() in the initializer list?
Base classes and members are initialized in the order of declaration in the class and not in the order you put in the initialization list.
Bases are always initialized before members, so the Base's constructor dereferences a pointer to an uninitialized object, which is undefined behavior.
This question already has answers here:
Calling child method from parent destructor in C++
(3 answers)
Closed 1 year ago.
#include <iostream>
using namespace std;
class Super {
public:
virtual ~Super() {
func();
}
virtual void func() {
cout << "super-class" << endl;
}
};
class Child : public Super {
public:
virtual void func() override {
cout << "child-class" << endl;
}
};
int main(void) {
Super super;
Child child;
return 0;
}
In this code, the default destructor of class Child is calling its super class Super's func() instead of its own overrided func(). And the output was:
super-class
super-class
I've tried this solution below.
#include <iostream>
using namespace std;
class Super {
public:
virtual ~Super() {
func();
}
virtual void func() {
cout << "super-class" << endl;
}
};
class Child : public Super {
public:
virtual ~Child() {
func();
}
virtual void func() override {
cout << "child-class" << endl;
}
};
int main(void) {
Super super;
Child child;
return 0;
}
And the output was:
child-class
super-class
super-class
But is there a way to let class Child automatically call its own func() in its destructor without virtual ~Child()?
By the time a base class destructor has started running, the derived class(es) have already been fully destructed. It (they) no longer exist(s). They cannot be called into. They are EX-objects! (Loosely paraphrasing Herb, paraphrasing the John.)
Level by level, as the object dies, the parts of it that have been destroyed are not left behind; they no longer exist. The type is adjusted accordingly upwards, and virtual calls resolve to the type being destroyed, until nothing is left of that object but a pile of bits.
Reading through a text book, I have come away with the impression that overriding virtual functions only works when using a pointer or reference to the object. The book demonstrates the creation of a pointer of the base class type pointed to an object the derived class type, and uses that to demonstrate a virtual function override.
However, I've now come across the following. Not a pointer in sight, and I was expecting that making function1 virtual would not make a difference, but it does. I'm clearly missing something here and would appreciate an explanation as to what it is. Sorry if my explanation isn't clear; also I expect this has been asked before, but was unable to come up with what to search on.
using namespace std;
class ClassA
{
public:
void function1(); // virtual or not?
void function2();
};
class ClassB : public ClassA
{
public:
void function1();
};
int main()
{
ClassA objA;
ClassB objB;
objA.function1();
cout << "\n";
objA.function2();
cout << "\n";
objB.function1();
cout << "\n";
objB.function2(); // Fourth call
cout << "\n";
}
void ClassA::function1() { cout << "ClassA::function1\n"; }
void ClassA::function2()
{
cout << "ClassA::function2\n";
function1(); // For the fourth call ClassA::function1()
// is called if ClassA::function1() is not virtual
// but ClassB:function1() is called if it is. Why?
}
void ClassB::function1() { cout << "ClassB::function1\n"; }
Many thanks for any help.
It's not a virtual function as it is not marked as one. It's simply a public function accessible from a derived class / object. Your code is not exhibiting polymorphic behavior either. That being said none of your functions are virtual nor overriding. Trivial example for polymorphic installation would be:
#include <iostream>
#include <memory>
class ClassA {
public:
virtual void function1() { // now virtual
std::cout << "ClassA::function1\n";
}
};
class ClassB : public ClassA {
public:
void function1() override {
std::cout << "ClassB::function1\n";
}
};
int main() {
std::unique_ptr<ClassA> p = std::make_unique<ClassB>();
p->function1(); // now calls class B function, overrides class A behavior
}
or through references:
int main() {
ClassB objB;
ClassA& ro = objB;
ro.function1(); // now calls class B function, overrides class A behavior
}
There is little benefit in marking functions as virtual and override if you are not utilizing polymorphic behaviour.
Example of virtual without explicit pointers :
class A
{
public:
virtual void f1()
{
cout << "A::f1()" << endl;
}
void f2()
{
f1();
}
};
class B : public A
{
public:
void f1() override
{
cout << "B::f1()" << endl;
}
};
int main()
{
A a;
B b;
a.f2();
b.f2();
}
function1 is not virtual, obj2 calls the classB function1 because it is a clasB object, the compiler first looks at the most-derived type for a function, then the leftmost base (and on through the bases of that base), and then the next base in multiple inheritance situations. If you took a classA * to obj2 and called function1 it would call the classA function1.
This question already has answers here:
What's the difference between the Derived class override the base class's virtual function with or not with a "virtual" prefix? [duplicate]
(2 answers)
Closed 5 years ago.
I have three following classes:
class A
{
private:
std::string device;
public:
std::string getDeviceType() { return device; };
void setDeviceType(std::string device) { device = device; };
virtual void doSomething() = 0;
virtual void doSomething2() = 0;
};
class B: public A
{
private:
public:
B(){ ; };
virtual ~B(){ ; };
void doSomething() { std::cout << "I am usual B" << std::endl; };
void virtual doSomething2() { std::cout << "I am usual B" << std::endl; };
};
class C : public B
{
private:
public:
C(){ ; };
~C(){ ; };
void doSomething() { std::cout << "I am C" << std::endl; };
void doSomething2() { std::cout << "I am C" << std::endl; };
};
main:
B *myHandler = new C();
myHandler->doSomething();
myHandler->doSomething2();
but output is not as expected, my expected output was I am usual B and then I am C, because doSomething() is a non virtual member of class B. But the real output was I am C and then I am C. Do you know why?
because of doSomething() is non virtual member of class B
This is where you are mistaken. In A you declare doSomething() as virtual. That means that it is implicitly marked virtual in classes that derive from it. So doSomething() in B is virtual which means you will call C's doSomething().
The reason is that doSomething is marked as virtual in class A. So it remains virtual in classes B and C because they inherit from class A.
As this function is virtual, it is called according to the real type of the object, which is C in your case, and you get the output: I am C.
Once marked virtual, it remains virtual in all derived classes.
In C you overrode both doSomething() and doSomething2(). You instantiate C, so the methods of C are called in both cases.
If you omitted the override in C of doSomething(), the output would be as you expected it.
KR,
Melle
Assuming I have code like this:
struct Base1 {
virtual void foo() = 0;
};
struct Base2 {
virtual void foo() = 0;
};
struct Derived : Base1, Base2 {
void foo() override {}
};
I am trying to produce a single override for several functions of different base classes with same name/signature.
Is such an overriding legal and well-defined in c++?
Is such an overriding legal and well-defined in c++?
Yes, it is perfectly legal and well defined as long as you override the virtual function in the derived class.
If you create an object of Derived structure and invoke the foo function it will invoke the overridden function.
The compiler will always search the called function from local to the global scope. So here compiler will check if foo is defined in the Derived scope if not found it will check in the Base scope and since you have provided the definition of foo in the derived scope the compiler won't check Base scope.
Try this code and you will get a better idea.
The output will be This is derived.
#include <iostream>
using namespace std;
struct Base1 {
virtual void foo() {
cout << "This is base1" << endl;
}
};
struct Base2 {
virtual void foo() {
cout << "This is base2" << endl;
}
};
struct Derived : Base1, Base2 {
void foo() {
cout << "This is derived" << endl;
}
};
int main() {
Derived d;
d.foo();
return 0;
}