You are wrong. Your base class has a pure virtual function, func4(). This must be implemented in a class that derives from the base class. Nowhere does your derived class have an implementation of func4().
First post: Makes no sense <edit: This is too harsh. It actually can be valid, but perhaps a confusing design>; func3 is not pure virtual in base class, but is pure virtual in derived class. Of course, you could still make it legal by making the necessary implementations, but it would be very confusing for the end user:
struct I {
virtualvoid func3();
virtualvoid func4() = 0;
};
void I::func3() { }
struct J : public I {
virtualvoid func3() = 0;
virtualvoid func4() = 0;
};
struct K : public J
{
void func3() override;
void func4() override;
};
void K::func3() { }
void K::func4() { }
int main()
{
K k;
}
1 2 3 4 5 6 7 8 9
struct I {
virtualvoid func3();
virtualvoid func4() = 0;
};
struct J : I {
virtualvoid func3();
};
Second post: Isn't necessarily wrong, but is incomplete to the point where nothing useful can be said about the class. (Theoretically, there could be other code that derives from J that is responsible for implementing func4, making both I and J be "abstract" classes.)
Is below code the right way to overload a pure virtual function? Can overload be only done if I am able to override it?
You are not using the word "overload" correctly. Overloading is when you have two functions with the same name, but one has different parameter types. (It gets more complicated when you overload between base and derived classes; by default, overload resolution won't look at the base class.)
If you have the same function (with the same signature) in both the base and derived class, but it isn't virtual, then you are shadowing the base-class function in the derived class.
"Overloaded" is not an action that is applied to a function, it's simply a description of two or more functions. Overloading and overriding are two separate concepts that are independent of each other.
// Example program
#include <iostream>
#include <string>
using std::string;
struct Base {
virtualint twice(int number) = 0;
string twice(string text)
{
return text + text;
}
};
struct Derived : public Base
{
using Base::twice; // enable overload resolution between base and derived
int twice(int number) override
{
return 2 * number;
}
};
int main()
{
Derived der;
std::cout << der.twice(21) << '\n';
std::cout << der.twice("hello") << '\n';
}
42
hellohello
(In this example, 'twice' is overloaded to deal with both ints and strings. The int overload happens to be a pure virtual function that is overridden in the derived class.)
"Should not" --> I would say, correct, they generally should not. But it's not really a rule, so I don't want to say strongly here that you shouldn't ever do it. It would just be a weird design, but maybe has its place somewhere.
Essentially, you're making the base class non-abstract, but the derived class is forced to be abstract.
My understanding is that a virtual function shall only be overridden by a pure virtual function if it is itself declared as pure virtual. Hence a pure virtual function must be overridden and overloaded.
It was already explained that "overloading" is completely unrelated thing; nothing to do with virtual or pure (although you can overload them too).
1 2 3
// two functions with name "twice". Overloadint twice(int);
string twice(string);
When class has virtual member function, classes derived from it can provide different behaviour, different implementation for the function.
When class has pure virtual member function, it is abstract. It cannot be used directly. You have to derive from it and provide non-pure implementation in the deriving class.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct Base {
virtualvoid foo() = 0;
};
struct Child : public Base
{
};
struct Grandchild : public Child
{
virtualvoid foo() override
{
std::cout << "Grandchild::foo\n";
}
};
The Child inherits Base. Child IS-A Base. Child has function void foo(), but it is pure virtual.
Base is abstract. Child is abstract.
The Grandchild is a concrete class, because it overridesvoid foo() with something concrete.
1 2 3 4 5 6 7 8
struct First {
virtualvoid bar() = 0;
};
struct Second : public First
{
virtualvoid bar() override = 0;
};
Does Second have different bar() than First? Different behaviour?
What I meant to say is that a virtual function shall only be overridden by a pure virtual function if it is itself declared as pure virtual. Hence a pure virtual function must be overridden, as you can see from your code here. In your code case, a pure virtual function overrides a virtual function, hence no issues seen in your code. Pure virtual functions can also be overloaded by regular virtual functions or non-virtual functions. Pure virtual functions need to be implemented in derived classes for instantiation. So in short pure virtual function is a function that must be overridden and overloaded right?
So my below code
1 2 3 4 5 6 7 8 9 10 11
struct I {
virtualvoid func3();
virtualvoid func4() = 0;
virtualvoid func4(double x, double y) = 0;
};
struct J : I {
virtualvoid func3() override = 0; //not acceptable as it overrides non pure virtual
virtualvoid func4() override = 0; //acceptable as it overrides pure virtual
virtualvoid func4(double x, double y); //overloading pure virtual. can this be done?
};
virtualvoid func4(double x, double y); //overloading pure virtual. can this be done?
Again, this is not overloading. This is overriding.
And yes, this MUST be done at some level. Without a definition of func4(double, double), all classes derived from class I would be abstract. It is not legal to instantiate an object of an abstract class.
Edit: Well, it is overloading also because func4 has 2 signatures in both I and J, but the important part of the answer is that this overrides I:func4(double, double).
If a base class function is defined as pure virtual, then the derived class(s) needs to provide a definition of the function if the derived class(s) is to be instantiated.
No class with a pure virtual function can be instantiated.
I dont think First::bar() and Second::bar() behaves differently here. What I am trying to figure out is that if its really necessary that a pure virtual function MUST be overridden?
struct A
{
virtualvoid foo( int ) = 0 ; // pure virtual
int a = 0 ;
};
struct B : A
{
// B does not override and implement the pure virtual function
// B is an abstract class; objects of type B can't be instantiated
// except as sub-objects of a further derived class
int b = 5 ;
};
struct C : B
{
// C overrides and implements the virtual function
virtualvoid foo( int ) override { /* ... */ }
// objects of type C can be instantiated as the most derived class
};
struct D : C
{
// D overrides and declares the function as a pure virtual
virtualvoid foo( int ) override = 0 ;
// D is an abstract class; objects of type D can't be instantiated
// except as sub-objects of a further derived class
};