There are a bunch of questions I have regarding pure virtual functions
First of all consider the following ABC class and its pure virtual function
class base{
public:
virtual void functionname(void) =0;}
First, a quick correction to your code:
class base {
public:
virtual void functionname(void) = 0;
}; // this semicolon is important
So the above is a pure virtual function that is you can't instantiate an object of the base class but can inherit other classes from it , am I right to this point ?I guess so .
You are correct. However, please note that
some compilers, whilst not standards-correct, may still allow you to instantiate a class containing pure-virtual functions directly. I suspect that you're looking for reasoning...
The idea behind pure-virtual functions stems from creating a member function(or 'method', if you prefer) that has no implementation. This would typically prevent the class from being properly instantiated as the object is incomplete and thus important things like sizes & such cannot be calculated. These calculations are important for vtable creation, among other things. Creating such a function as a 'virtual' one permits a derived class to override it and thus create an implementation. In so doing, all the calculations can be made appropriately and thus the derived class can be instantiated. Because the name still exists, the size of a pointer can be used for some vtable calculations and addressing the pure-virtual function is easy as an offset. Thus, as per the rules of inheritance, any derived class can be handled as the same type as the base class. This is well-used by proper exception handling.
class shape {
public:
virtual void Draw(void) = 0;
};
class triangle : shape {
public:
void Draw(void); // implemented elsewhere
};
class square : shape {
public:
void Draw(void); // implemented elsewhere
};
int main(void) {
shape *s; // note that this variable can be used to point to any instance of a class that is derived from the base 'shape'
bool isSquare;
// a bunch of other crap would go here
if (!isSquare) {
s = new triangle();
// blah, blah, blah
} else {
s = new square();
// blah, blah, blah
}
// more crap
return 0;
}
Note that this feature works very, very well for templates.
Q) Is it necessary that they shouldn't have a body(code block/function definition)? what if virtual void functionname(void)=0{coud<<"Wadap dawg\n";}
Valid , if invalid then how can you use this function which is nothing more than a prototype ?
Some compilers won't permit you to create an implementation of pure-virtual functions; others will. Generally this is a bad idea, though, because the '= 0' is essentially defining that function as pointing to NULL. I believe Stroustrup would have a fit concerning undefined behavior between different platforms.
Q) suppose you derive a class from the abstract base class , then will it inherit the pure virtual function ? IF so , then again it is nothing more than a prototype how can it be used ?
In the derived class you would create an implementation. Of course, if you were deriving another abstract class, the implementation is still optional but then again you wouldn't be able to instantiate it either. At some point there really should be an implementation.
Q) Suppose myfunction is a pure virtual function in the base class , and you have added a function named myfunction in the derived class , which function be used by the instance of derived class ?(I believe the overloaded one {considering that overloading this function in the derived class is legit}) , but what if you force to use the base one with the scope resolution operator like BASE::myfunction();
Okay, you're technically asking two distinct, but related, questions here(one of which is actually really good...not to invalidate your other queries).
First; if you derive a non-abstract class from an abstract class you should create an implementation of all pure-virtual functions from the base class. This should always guarantee that the derived class's functions are used. Just as you can calculate the offset of data members within a struct(or array) from the base address, so can you with class. This means that the offset of the implementation will be the same from the base address of the instance as it would be as calculated in the base class. I know this isn't necessarily very clear, especially to others who may be perusing over this topic without an appropriate understanding of the language. I'll try to demonstrate with some basic code.
struct s_test {
char a, b, c[6];
int i, j, k;
};
struct s_test Test;
The size of 'Test' is the size of 'char' times the number of 'chars' found in the structure 's_test' summed with the size of 'int' times the number of 'ints' found in the same structure. Put more simply, the size is the sum of all the parts. In this case, there are 8 chars(a = 1, b = 1, c = 6; 1 + 1 + 6 =
and 3 ints. Assuming, on a 32-bit platform, that an 'int' is 32 bits(4 bytes), the size of the variable 'Test' is (1 + 1 + (1 * 6)) + (4 * 3); so 20 bytes. The location of any value within that variable can be calculated from the base address; 'Test.j' is located at &Test + (1 + 1 + (1 * 6)) + (4 * 1) or rather an offset of 12 bytes from the base address of the variable 'Test'.
This same principle can be applied to classes. The functions are stored as pointers to the instructions to be executed. Thus, if an abstract class has a pure-virtual function called 'myfunction' located at an offset of 30 bytes(for instance) from the base address, then it will be located at the same offset in the derived class. This is true even if the derived class implements additional functions and variables because such additions are appended. In effect the method is being called via function pointer.
Second; if you force to use the base implementation where that target implementation is a pure-virtual function, the behavior is 'undefined'. Typically, if the compiler somehow even allows it, you will probably end up with a crash as you would be attempting to run code located at a null pointer. On the other hand, it is possible(especially for managed code) that calling the base implementation would simply reference the current implementation and thus the operation would be pointless because you would still be using the derived class's implementation. Then again there is another possible case where it could somehow be implemented as not having a base class for that abstract function and, in effect, 'nothing' strange would happen(where again you will still be forced to use the derived class's implementation). Of course there could be more but that is why it is considered 'undefined' behavior...no one really knows for sure.
Q) Why would you rather use an abstract base class in the first place . why not just use protected inheritance and save all the crap ?
There's lots of reason to use an abstract base class. The 'shape' example given earlier is actually fairly common. It is a common technique in various data structures and common paradigms in different specializations of code. Game programming will use it heavily as will object-oriented hardware engineering software and more. Perhaps your understanding of protected inheritance is a little fuzzy. These are different concepts. I'll not explain the protected inheritance here as it's beyond the scope of this thread.
Q) can you create a pointer/reference variable to the base type and upcast it to point towards the derived type ?
base*P_P=NULL; //where base is an ABC class
P_P=new derived;//points toward a location allocated dynamically for aderived object , valid , why ?
Absolutely! This is one of the most-used cases. Consider an abstract 'vehicle' class that has pure-virtual functions 'move', 'forward', 'turn', etc. Perhaps an abstract sorter that has a pure-virtual comparator function. You could even have an abstract encryption class with a pure-virtual CSPRNG function. The flexibility offered by this feature is incredible and its usefulness is indescribable.
Hopefully you understand this topic a bit better. I'm sorry if I've confused you on anything. If you need clarification on something, just ask.