#include <iostream>
class A {
public:
void foo( ){
std::cout << "Calls A::foo()\n";
}
};
class B : public A {
public:
void foo( ){
std::cout << "Calls B::foo()\n";
}
};
int main() {
A* obj1 = new B;
obj1->foo(); // Calls A::foo()
obj1->A::foo(); // Calls A::foo()
A* obj2 = new A;
obj2->foo(); // Calls A::foo()
B* obj3 = new B;
obj3->foo(); // Calls B::foo()
return 0;
}
#include <iostream>
using namespace std;
// Base class
class Query {
public:
virtual void display() const {
cout << "Query::display()" << endl;
}
};
// Derived class
class NameQuery : public Query {
public:
void display() const override {
cout << "NameQuery::display()" << endl;
}
void extra() const {
cout << "Extra function in NameQuery" << endl;
}
};
int main() {
NameQuery nq;
// Call through derived object – correct behavior
nq.display(); // Output: NameQuery::display()
// Object slicing: only Query part is copied
Query q = nq;
// Call through base object – slicing has occurred
q.display(); // Output: Query::display() ← wrong if you expected polymorphism
// Error: q has no member of extra()
q.extra();
return 0;
}
virtual keyword within the class declaration. If the definition is placed outside the class, the keyword virtual must not again be specified.
#include<iostream>
class Base {
public:
virtual void foo();
};
class Derived : public Base {
public:
void foo() override {
std::cout << "Calls Derived::foo()\n";
}
};
// Correct
void Base::foo(){
std::cout << "Calls Bar::foo()\n";
}
// Incorrect
virtual void Base::foo(){
std::cout << "Calls Bar::foo()\n";
}
int main(){
Base* ptr = new Derived;
ptr->foo();
return 0;
}
const, or declared a second parameter, the derived instance would not override the active base class instance. The return value must also be the same, with one exception: The return value of the derived instance can be a covariant type of the return value of the base instance.
#include <iostream>
using namespace std;
class Animal {
public:
virtual Animal* clone() const {
cout << "Cloning Animal" << endl;
return new Animal(*this);
}
virtual void speak() const {
cout << "Animal speaks" << endl;
}
virtual ~Animal() {}
};
class Dog : public Animal {
public:
// Covariant return type: returns Dog* instead of Animal*
Dog* clone() const override {
cout << "Cloning Dog" << endl;
return new Dog(*this);
}
void speak() const override {
cout << "Woof!" << endl;
}
};
int main() {
Animal* a1 = new Dog();
Animal* a2 = a1->clone(); // Calls Dog::clone, returns Dog*, but assigned to Animal*
a1->speak(); // Woof!
a2->speak(); // Woof!
delete a1;
delete a2;
return 0;
}
#include <iostream>
#include <vector>
class A {
public:
virtual void foo( ) = 0;
};
class B : public A {
public:
void foo( ){
std::cout << "Calls B::foo()\n";
}
};
int main() {
A* obj = new B;
// invoke B::foo() dynamically through virtual mechanism
obj->foo(); // Calls B::foo()
// Error: undefined reference
obj->A::foo();
// invalid new-expression of abstract class type ‘A’
A* obja = new A;
return 0;
}
#include <iostream>
#include <vector>
class A {
public:
virtual void foo( ){
std::cout << "Calls A::foo()\n";
}
};
class B : public A {
public:
void foo( ){
std::cout << "Calls B::foo()\n";
}
};
int main() {
A* obj = new B;
// invoke B::foo() dynamically through virtual mechanism
obj->foo(); // Calls B::foo()
// invoke A::foo() statically at compile-time
obj->A::foo(); // Calls A::foo()
return 0;
}
Why might we wish to override the virtual mechanism? Often, for efficiency.
foo(), however, is not determined at run-time; rather, it is determined at compile-time and is based on the type of the object through which the function is being invoked. When foo() is invoked through obj1, the default argument is determined by the declaration of A::foo(), which is 1. When foo() is invoked through obj2, the default argument is determined by the declaration of B::foo(), which is 2.
#include <iostream>
#include <vector>
class A {
public:
virtual void foo( int a = 1 ){
std::cout << "Calls A::foo(int a = " << a << ")\n";
}
};
class B : public A {
public:
void foo( int a = 2 ){
std::cout << "Calls B::foo(int a = " << a << ")\n";
}
};
class C : public B {
public:
void foo( int a = 3 ){
std::cout << "Calls C::foo(int a = " << a << ")\n";
}
};
int main() {
A* obj1 = new B;
obj1->foo(); // a = 1
B* obj2 = new C;
obj2->foo(); // a = 2
return 0;
}
But what if we really wish for the actual default argument passed to foo() to be based on the actual instance of the function invoked? Unfortunately, the virtual mechanism does not support this directly. One programming solution is:
void
base::foo( int ival = base_default_value )
{
int real_default_value = 1024;
if ( ival == base_default_value )
ival = real_default_value;
// ...
}
void
derived::foo( int ival = base_default_value )
{
int real_default_value = 2048;
if ( ival == base_default_value )
ival = real_default_value;
// .
}
#include <iostream>
class Root {
public:
virtual ~Root() {
std::cout << "Root destructor\n";
}
};
class Base : public Root {
public:
~Base() {
std::cout << "Base destructor\n";
}
};
class Derived : public Base {
public:
~Derived() {
std::cout << "Derived destructor\n";
}
};
int main() {
Root* obj = new Derived();
delete obj;
// Output:
// Derived destructor
// Base destructor
// Root destructor
}
new is called before the object exists, there’s no object instance and no vtable — so you cannot make the operator new virtual.new cannot be virtual, creating a duplicate of an object through pointer is considerably less trivial. The solution is:
#include<iostream>
class Base {
public:
virtual Base* clone() const = 0;
virtual ~Base(){};
virtual int get() = 0;
};
class Derived : public Base{
public:
Derived(int m) : _m(m) {}
Base* clone() const override {
return new Derived(*this);
}
int get() override { return _m; }
int _m;
};
int main() {
Base* obj1 = new Derived(-1);
// using static_cast
// --> Cons: the type of obj1 must be known at compile time
Base* copy = new Derived(*static_cast<Derived*>(obj1));
std::cout << copy->get() << "\n";
delete copy;
// using dynamic_cast
// --> Cons: must check all derived types at runtime
Base* obj2 = new Derived(-1);
Derived* derivedPtr = dynamic_cast<Derived*>(obj2);
if (derivedPtr) {
Base* copy = new Derived(*derivedPtr); // safe deep copy
std::cout << copy->get() << "\n";
delete copy;
} else {
std::cout << "obj1 is not a Derived\n";
}
delete obj2;
// using clone
// --> Best solution
Base* copy2 = obj1->clone();
std::cout << copy2->get() << "\n";
delete copy2;
}
Virtual functions do not behave polymorphically during base class construction or destruction. Because during construction, the derived part of the object does not yet exist. And during destruction, the derived part of the object has already been destroyed. So:
This prevents accessing uninitialized or destroyed data in derived classes, which could lead to crashes or undefined behavior.
#include <iostream>
class Base {
public:
Base() {
std::cout << "Base constructor\n";
call(); // virtual function call inside constructor
}
virtual ~Base() {
std::cout << "Base destructor\n";
call(); // virtual function call inside destructor
}
virtual void call() const {
std::cout << "Base::call()\n";
}
};
class Derived : public Base {
public:
Derived() {
std::cout << "Derived constructor\n\n";
}
~Derived() {
std::cout << "Derived destructor\n";
}
void call() const override {
std::cout << "Derived::call()\n";
}
};
int main() {
Derived d;
return 0;
}
Output:
Base constructor
Base::call()
Derived constructor
Derived destructor
Base destructor
Base::call()