Polymorphism c++ - c++

In some books there is written that class that declares or inherits a virtual function is called a polymorphic class.
Class B doesn't have any virtual functions but passes more than one is-a test.
Class C has one virtual function but doesn't inherit.
class A {};
class B : public A {};
class C
{
public:
virtual void f () {}
};
is class B or C polymorphic ?

2003: 10.3/1 states, clearly:
A class that declares or inherits a virtual function is called a polymorphic class.
You actually said this yourself, word-for-word, so I don't really understand what the question is.
C (and its descendants, if you add any) is polymorphic; A and B are not.
Note that, in a wider OOP sense, you can always perform some "polymorphism" in that C++ always allows you to upcast; thus all objects that inherit can be treated as a different (but related) type.
However, the term "polymorphic" is defined slightly differently in C++, where it has more to do with whether you can downcast as well. If you don't want to be confusing like the C++ standard, you might call this "dynamic polymorphism".

Per the standard, "A class that declares or inherits a virtual function is called a polymorphic class."
Because neither A nor B declare or inherit a virtual function, they are not polymorphic.
C declares a virtual function, so it is polymorphic.

class C is polymorphic, meaning that using dynamic_cast or typeid on a C& will do a runtime type check, and calling member functions through a C& or C* will use virtual dispatch.
(Of course, the as-if rule allows the compiler to avoid the runtime dispatch under some condition when it knows the runtime type in advance, such as when you just created the object.)
As #Bill mentioned in a comment, that isn't just what some books say, it's the definition of polymorphic class, found in the C++ standard (section 10.3, [class.virtual]):
Virtual functions support dynamic binding and object-oriented programming. A class that declares or inherits a virtual function is called a polymorphic class.

Related

Is-a relationship without virtual functions c++

I couldn't find examples of is-a relationship without virtual functions. Is a following pattern ok?
class Base {
public:
void doSomethingWithX() {/*implementation here*/}
protected:
~Base(){}
private:
int x_;
};
class Derived : public Base {
//Add some other functionality but inherit doSomethingWithX and its implementaion
public:
void doSomethingWithY();
~Derived(); //And document that nobody should inherit further from this class.
private:
int y_;
};
foo(Base* ptr) {
//Do something via Base interface
}
Derived d;
foo(&d);
Edit: I was asked to clarify what I mean by "is this pattern ok".
Does this kind of inheritance satisfies what is usually needed from is-a relationship? Liskov substitution principle etc.
Is it safe to use Derived objects via pointer to Base? (or I miss some problem here).
I'm asking this because there is often written that base class destructor should be either public and virtual or protected and non-virtual. But I never met real examples of public inheritance without non-virtual functions.
It's okay for what you're doing here; You can pass a pointer to Derived and it can bind to a pointer of Base just fine. It's not possible to say whether it satisfies the Liskov subtitution principle because we do not know the invariants of your classes.
Just recognize that without any virtual functions, you cannot use polymorphism. This goes beyond simply overriding function behavior; you'll never be able to perform a dynamic_cast of a pointer to Base to a pointer to Derived.
Additionally, if nobody should derive from Derived, then mark it final, which is available since C++11
There are two types of polymorphism, both implementable in C++: static and dynamic. The latter is what you get with virtual functions and pointers to base classes, in which the behaviour is specialized depending on the real type of object pointed to.
The former can be achieved by writing a template, in which your template type is assumed to have certain interfaces. The compiler will then enforce that when instantiating the template, at compile time. You can provide additional enforcement using SFINAE and/or static_asserts to ensure the type used "is a" or rather conforms to the templated interface used by your code. Note there is not really a straightforward way of defining this interface as with a base interface class, aside from the aforementioned methods.
Note that static polymorphism is what you get at compile time. No dynamically chosen types at runtime. You'll need some form of base class for that.

Inherited pure virtual functions

Let's imagine the following situation: A is an abstract class defining a pure virtual function void f(); B is a class that implements a function void f(); C inherits from both A and B:
struct A
{
void virtual f() =0;
};
struct B
{
virtual void f() { }
};
struct C : public A, public B
{
};
The question could be: Is C an abstract class? The requirements deriving from A being abstract are that the subclass implements the virtual function void f(). C does not implement it directly, but inherits it from B.
I can already answer this question: Yes, C is an abstract class. If you try to instantiate an object of type C you'll get a compilation error. So the actual question is: Why is C an abstract class?
I suppose that the fact that A::f and B::f have the same name and signature is not enough to draw a correspondence between these functions so to say that B::f implements A::f. From a technical point of view I can see that these functions "reside" in different parts of the object of type C (though I'm not really sure that my understanding is complete). But from a conceptual point of view I could easily imagine a situation where a class C wants to be an implementation of the abstract class A and, in order to implement the pure virtual function f, it uses the implementation of one of its parent classes. The solution is probably to do:
struct C : public A, public B
{
virtual void f() { B::f(); }
};
, which worked in my experiment. But is this trick necessary?
EDIT:
Further question: Is the order in which C inherits from A and B relevant? Would it change something if I wrote the following?
struct C : public B, public A
{
};
The answer (again, I test my codes, then I try to ask non-trivial questions) is no, it does not change anything. But in this case (correct me if I'm wrong), C::f, if implemented, would override B::f, not A::f. Since A::f would not be accessible using a C object does it make sense to request that it is implemented?
C also inherits from B doesn't make a bit of difference when it considers the functions inherited from A. So, when it compiler sees that C doesn't override pure virtual from A, it makes it an abstract class.
The requirements deriving from A being abstract are that the subclass implements the virtual function
Not quite. The requirement is that the subclass overrides the pure virtual function, with a non-pure function. A function in one base class doesn't override one in another base class; C itself must declare an override to be non-abstract.
But is this trick necessary?
Yes. You have to override the function in a class derived from A; in this case, that means C.
Is the order in which C inherits from A and B relevant?
No, the declaration order makes little difference. The override must be declared in a class derived from A.
But in this case (correct me if I'm wrong), C::f, if implemented, would override B::f, not A::f.
It would override both, regardless of the declaration order of the base classes.
Since A::f would not be accessible using a C object does it make sense to request that it is implemented?
Both are still accessible (although the name will need to be qualified since an unqualified f is ambiguous). The pure function still needs to be overridden to make the derived class non-abstract.
Since the other answers haven't been updated for your new questions, here are the answers to them.
But in this case (correct me if I'm wrong), C::f, if implemented, would override B::f, not A::f.
You're half wrong. Both A::f and B::f are overridden by C::f regardless of the order of inheritance.
Since A::f would not be accessible using a C object does it make sense to request that it is implemented?
But A::f is accessible using a C object. Consider this, rather typical use of inheritance:
void call_f(A& a) {
a.f();
}
int main() {
C c;
call_f(c);
}
If C doesn't override A::f, then this couldn't possibly work. It makes sense that a concrete subclass of A must implement A::f.

Polymorphism vs regular inheritance?

I use polymorphism so frequently, but it suddenly dawned upon me. I have the case where my code is:
class A{
class B : public A{
class C : public A{
and I use class A as a polymorphic parameter type for passing in B or C sub types:
//Accepts B and C objects
void aMethod(A* a){
However, I gave A a virtual destructor- this is the only reason A (and B and C) contain a vtable pointer.
So my question is, if I hadn't declared A with a virtual destructor, then A wouldn't be polymorphic- I wouldn't be able to pass objects of type B or C in aMethod()??
So is non-polymorphic inheritance just about sharing code, whereas polymorphism (the base class must have a vtable) allows passing sub types as arguments of the base class type?
In this code you provide,
void aMethod(A a){
the a formal argument is not polymorphic. It's passed by value. When you pass in a B or C object as actual argument, you're just slicing it down to an A, that is, you're copying the A base class sub-object only.
Regarding
” So is non-polymorphic inheritance just about sharing code, whereas polymorphism (the base class must have a vtable) allows passing sub types as arguments of the base class type?
it combines two questions that have to be treated separately.
Inheriting from a non-polymorphic class is about sharing of code, yes, but it also introduces an is-a relationship, which can be important for e.g. passing by reference.
Inheriting from a polymorphic class (one with one or more virtual member functions) allows you to override base class functionality, or to implement it where the base class leaves that as a derived class responsibility – typically by having pure virtual member functions. This means that member functions in the base class can call your derived class’ member functions. Also, that calling member functions via a base class pointer or reference, can call your derived class’s implementations.
Non-polymorphic types also contain a subobject for each base class, and upcasts are still implicit.
You can therefore pass objects of derived classes just fine even when there is no polymorphism. The receiver will act on the base subobject, just as happens for data members and non-virtual functions of polymorphic types.
A class with its destructor the only virtual method, like your class A, is an oddity. AFAIK, such a class has no necessity in well designed code.
From your question, it is not clear whether the virtual destructor is needed (i.e. if you ever call the destructor of classes B or C through a reference or pointer to class A), but if it is, your code smells. If it is not, then simply make the destructor non-virtual.

Meaning of 'virtual' in classes

In following case, virtual is used to solve the diamond problem to have sub-object of class A shared with B and C.
For example:
class A { };
class B : virtual public A { };
class C : virtual public A { };
class D : public B, public C { };
Does this type of inheritance will be resolved at compile-time or run-time? I mean, how different is the meaning of virtual when used on functions and classes? Is there a concept of dynamic binding when virtual is used to inherit from base class?
Inheritance doesn't have to be "resolved", as you put it, so the question isn't very clear.
The important difference is between ordinary inheritance and virtual inheritance. If you inherit ordinarily, i.e. B : A, C : A, then the class D : B, C has two subclasses of type A, namely D::B::A and D::C::A. On the other hand, if B and C inherit virtually from A, then the ultimate subclass composition will be deferred until you define the final type. That is, B : virtual A and C : virtual A themselves each have a virtual subclass A which would become real if you were to instantiate either B or C. On the other hand, if you derive from the classes further, then the most derived class will contain only one subclass of type A.
Perhaps you may like to consider the analogy with member functions. If each derived class adds a member function of the same name as a base function, you end up with several distinct functions. On the other hand, if the base function is virtual, then you only ever have one function, which is defined in the most derived class. You still have some sort of function in each intermediate class (assuming the function isn't pure-virtual), but only the final class defines the "active" definition.
Virtual inheritance has an effect on constructors, namely that the virtual-base constructor (i.e. A() in the example) is called directly by the most derived class, i.e. D, and not by B or C. If you will, this is because only D "knows" that it contains only one A-subclass, so it is directly "responsible" for it. B and C just hold a virtual placeholder that gives way to the ultimate, most derived class.
Accessing a member function through any base pointer/reference behaves just as expected and is resolved in the usual fashion (i.e. dynamically, in general), but that has nothing to do with virtual inheritance. The actual function lookup may be a bit more complicated as it may involve an extra level of indirection, but that doesn't change anything fundamental.
Virtual inheritance is resolved at runtime.
Virtual inheritance, just like virtual functions, means that each instance of the class has access to runtime data that describes where the virtual thing can be found.
It's described failry well at How C++ virtual inheritance is implemented in compilers?
Does this type of inheritance will be resolved at compile-time or run-time?
Inheritance defines the shape (memory footprint) of the types and it is resolved always at compile time. On the other hand, access to the members of the base type will be resolved at runtime, the reason being that intermediate types in the hierarchy cannot know where the base subobject will be laid in memory in the most derived type.
I mean, how different is the meaning of virtual when used on functions and classes?
Types and functions are different at all levels, so there is not much to say here. The only common thing is that there is a part of the work that cannot be fully resolved at compile time. In particular, the similarity is that code that uses a virtual function depends on a vptr (virtual table pointer) to find the proper vtable (virtual table) for the most derived type, and in a similar way, access to the base object requires the use of a pointer stored in each subobject of a type that derives virtually from the base.
You can read more (about a particular implementation, all this is not part of the standard) in the Itanium C++ ABI, and in particular in the Non-POD Class Types.
As a brief summary, whenever a type D inherits virtually from a type B, the D subobject will contain a hidden pointer to the B subobject. The need for that pointer arises from the fact that the relative position of the B subobject with respect to D can change with further inheritance.
It is my understanding that virtual classes resolves compile time ambiguity. For example assume that both B and C have a getSize method.
Without virtual, a call to D.getSize attempts to use the base class getSize method. Since both B and C each have a getSize method, the compiler is unable to properly resolve the ambiguity and the code will not compile.
With virtual, a call to D.getSize uses the decedent getSize method allowing the code to compile correctly.

Doesn't putting a "virtual destructor inside an interface" make it, by definition, not an interface anymore?

So here is the box I am in. I want to understand why it is important to have a "virtual destructor inside your interface class". You will see why that stuff is in quotes if you can hang to the end... I also want to get all the vocabulary absolutely correct. Here is where I am at with the process so far:
Sometimes you have base classes, sometimes you have derived classes which inherit from base classes.
If you have a base-pointer that finds itself pointing to a derived-object, and further you want a member function call made from that base-pointer-pointing-to-a-derived-object to behave as if it had actually been called from the derived object, then the member function you call had better be declared virtual in the base class.
An interface is any class with only pure virtual functions. If you derive a new class from this interface class and implement all the pure virtual functions, then you can finally create an instance of the derived class.
You can never have an instance of an interface class, BUT you can have an instance of a pointer-to-interface-class.
In the case where you have a pointer-to-interface-class that actually points to an object of the derived class (actually, I guess it would always have to if #4 is correct), and if you decide to delete that object through your pointer, then if you don't have a "virtual destructor inside your interface class", your intention to destroy the derived object will only be executed as a call to destroy the base object (i.e. the interface class) and since there is no virtual destructor, things won't ever get to the point where the destructor for the derived object is actually called -- thus causing memory leaks.
Phew. Okay, if that sounds right, onto my question. Is it enough just to declare a virtual destructor inside your interface like this:
virtual ~iFace();
That looks wrong to me... so what happens if you make the destructor pure virtual like this:
virtual ~iFace() = 0;
Since they are just declarations, do either of these count for being a "virtual destructor inside your interface class"? Can you even have a declared but un-defined destructor? Only if it is pure virtual I would guess...
Anyway, so getting back to the title question... I really am going as fast as I can... Here is the money shot... If your "virtual destructor inside your interface class" requires at least an empty definition like this:
virtual ~iFace() {};
Then that member function is not pure virtual (can't be because you gave it a definition) and therefore your class is no longer an interface (it does not only contain pure virtual member functions).
This would imply that if you define a virtual destructor for your interface, then you no longer have an interface (but just some abstract base class). Is this just an abuse of language? Do I understand what is going on?
note: All this came from asking myself "What is an interface?" and then reading this question's answers: How do you declare an interface in C++?
Hope that wasn't too long a walk for too short a ride, but I am determined to completely understand these concepts and their associated vocabulary.
Why Abstract class destructor should be virtual and have a definition?
Calling delete on a polymorphic Base class pointer pointing to a Derived class object & the Base class not having a virtual destructor causes an Undefined Behavior.
So you do need to declare the destructor of the polymorphic Base class as virtual. Once you declare your destructor explicitly virtual, you do need to provide a definition for it. This is because the compiler by default generates(defines) a destructor for every class but if you explicitly declare the destructor then the compiler does not do so and leaves it for you to provide a definition for your own destuctor. It makes sense because the compiler sees explicit declaration as an indication that you want to do some non trivial operations(even if you are not in need of doing so) in the destructor and it provides you the opportunity to do so by forcing you to give the definition.
Myth 1:
There is something called an Interface in C++.
NO
C++ as a language does not provide an Interface
What you refer to as Interface is called an Abstract class in C++. Abstract Classes are used to simulate the behavior of Interface in C++.
What is an Abstract class?
By definition an abstract class should have at least one pure virtual function.
Myth 2:
All functions inside Abstract class need to be pure virtual.
NO
Abstract classes do not require all functions inside them to be pure virtual. An object of an Abstract cannot be created if it has at least one pure virtual function. Though, as you correctly mentioned you can create pointers to it.
Myth 3:
Pure virtual functions cannot have a definition.
NO
It is perfectly valid for Pure virtual functions to have a definition.
Why would I ever need a Pure virtual function with definition?
Code speaks louder then words, So here is a simple example:
Warning: Uncompiled code only for demonstration
class IMyInterface
{
int i;
int j;
public:
virtual void SetMembers(int ii, int jj)=0;
};
/*The pure virtual function cannot be inline in the class definition*/
/*So this has to be here*/
void IMyInterface::SetMembers(int ii, int jj)
{
i = ii;
j = jj;
}
class Myclass: public IMyInterface
{
int k;
int l;
public:
virtual void SetMembers(int ll, int m, int a, int b)
{
k = ll;
l = m;
IMyInterface::SetMembers(a,b);
}
};
int main()
{
MyClass obj;
obj.SetMembers(10,20,30,40);
return 0;
}
C++ doesn't have a native interface entity. Interfaces are implemented as regular classes.
What makes a class an interface in C++ is, therefore, not something that has universal agreement. Personally I consider a class to be an interface if it has no data members, no user-declared constructors and all of its functions are pure virtual - with the possible exception of its destructor - and all of its base classes, if any, are also interfaces. If a class doesn't quite fit all of these properties I might refer to it as a "fat" interface (generally not a compliment!).
If you want to delete dynamically allocated polymorphic classes through a pointer to a base class (such as an "interface" class) then the base class destructor must be declared virtual. This means that it must be a user-declared destructor and not an implicitly declared destructor which would be non-virtual.
Once you declare a destructor explicitly, you must provide an implementation for it. (A base class destructor will always be used when you destroy an instance of any class derived from it whether or not the base class destructor is declared pure virtual, virtual or non-virtual.) This is purely an C++ language implementation detail. It doesn't mean that your base class is any less of an "interface", if you have an interface class then it is very likely that the implementation of the destructor will be empty in any case - you have no members or base classes with members to worry about.
If your interface has at least some pure virtual functions then there is no real merit to marking the destructor as pure, your interface class is already an abstract class. Derived class destructors don't technically override base class destructors so you're not requiring derived classes to provide user-declared destructors or anything like that.
Declaring a destructor as a pure virtual also robs you of the ability to provide the definition of the destructor inline in the class definition, although this is a minor detail.
"An interface is any class with only pure virtual functions"
-- The concept in C++ is called abstract class. An abstract class is a class with at least one pure virtual function. It doesn't require that all of its member functions are pure virtual though. You cannot instantiate any abstract class.
"This would imply that if you define a virtual destructor for your
interface, then you no longer have an interface (but just some
abstract base class). Is this just an abuse of language? Do I
understand what is going on?"
-- On the contrary, you must provide a definition for the destructor even if it is pure virtual because destructors are always called in a down-up manner in inheritance hierarchy.
Standard 12.4:
A destructor can be declared virtual (10.3) or pure virtual (10.4); if any objects of that class or any derived class are created in the program, the destructor shall be defined.
Example:
class A
{
public:
// this is stil a pure virtual function
// when there is a definition
virtual ~A() = 0;
};
class B: public A
{};
int main()
{
// fail to link due to missing definition of A::~A()
B b;
}
OK.
OK; if the member function is not declared virtual in the base class, the one from the base class is called; if the member function is neither defined nor declared pure virtual in the base class, you get an error.
In C++ you don't have interfaces as you have in Java and C#; abstract base classes in C++ combine interfaces and abstract classes as they are present in the latter two languages. A C++ class is abstract if it has at least one pure virtual member function.
Replace interface with abstract class.
Formally you cannot make assumptions on what happens if you delete a derived class from a pointer to a base class if the base class's destructor is not declared virtual.
Given all this, in general your abstract base class will already have some pure virtual member function which ensure that it won't be possible to instantiate it, so the usual way of doing things is to define an inline virtual destructor that does nothing.