This question already has answers here:
What is the main difference between Inheritance and Polymorphism?
(18 answers)
Closed 9 years ago.
I read up on inheritance and polymorphism but I still can't distinguish what's the difference between both of them.
From what I knew, inheritance is e.g(a derived class inheritance methods from base class and method overriding can be performed as well.) so then what is polymorphism? are both inheritance and polymorphism somehow have the meaning?
Please correct me as I know that I am wrong. Thanks
In this case, we have inheritance but no polymorphism:
struct SimpleBase {
int i;
int get() const { return i; }
};
struct SimpleDerived: public SimpleBase {
int get() const { return i + 7; }
};
an instance of SimpleBase (or a reference or pointer to it) is always exactly that, and the derived class can't change its behaviour. For example:
int foo(SimpleBase const &obj) { return obj.get(); }
will always call SimpleBase::get, even if I pass in an instance of the derived type.
Conversely, with polymorphism, a derived class can override base class methods with its own versions:
struct PolyBase {
int i;
virtual int get() const { return i; }
};
struct PolyDerived {
int get() const { return i + 7; }
};
int foo(PolyBase const &obj) { return obj.get(); }
Now foo calls a different method depending on the derived type passed in, without knowing which derived type it is.
So with polymorphism, a whole family of types can share a common interface, and you can write code once that operates on the interface, without having to know about all the different derived types.
The form of polymorphism shown above is run-time polymorphism: it generates code that figures out which implementation of each virtual function to call when it runs.
There is also compile-type polymorphism, which doesn't require inheritance at all, and instead uses templates.
Say you want to write a sorted container (like std::map) - you don't want to limit it to storing a particular data type, but you do need some way to compare two elements to see which is bigger.
The run-time approach might provide an abstract base class, like
struct LessThanComparable {
virtual bool operator< (LessThanComparable const &) const = 0;
};
and require every type you want to put in your container, to derive from this and implement operator<. Then, you can write if (a < b) in your container code, and the right function for the type you're storing will be called (*).
// requires inheritance from abstract base class,
// uses virtual call to operator<
bool less_than(LessThanComparable const &a, LessThanComparable const &b) {
return a < b;
}
The compile-type approach actually used (**) in the STL is to state that every stored type must model the LessThanComparable concept, by providing a suitable operator<. However, this is resolved at compile time, and no common base class is required.
// doesn't require any inheritance, doesn't use virtual function call,
template <typename T>
bool less_than(T const &a, T const &b) { return a < b; }
(*) note also that implementing operator< isn't trivial, because a < b can be called when a and b have different derived types. In the template version, we know they both have the same type T.
(**) ok, so the default std::less has the LessThanComparable requirement, or you can provide an alternative StrictWeakOrdering.
In farmer`s words, polymorphism is when you work with "base" class (called an interface in some cases) without knowing what the actual implementation really is. Inheritance can be used with or without polymorphism (i.e. when you use inheritance but always know what specific class of object you are dealing with, even if it is inherited from something else, is not a polymorphism). But polymorphism cannot be used without inheritance (it just stops making any sense).
Polymorphism allows you to morph the class back and forth between its inherited parent classes. The following is legal, if Dog and Cat class inherits from Animal
void takes_animal(Animal &animal) { }
Dog dog;
Cat cat;
takes_animal(dog);
takes_animal(cat);
Inheritance is an implementation technique. Polymorphism is an
aspect of one of the things you can implement with it. (It's
not the only thing. For example, inheriting from
std::iterator has nothing to do with polymorphism.)
Your are right about inheritance but it is not that simple. Overloading and Overriding are also important functions of inheritance. While, polymorphism is about creating polymorphic arrays like if parent class is fruits and apples are objects then you can define objects as type of fruits and call general function. Also creating pure virtual function will prevent parent class to make it's instances.
Related
I'm pretty experienced in C++, but I find myself struggling with this particular design problem.
I want to have a base class, that I can stuff in a std::map, with a virtual function that can be called generically by a method that is querying the map. But I want to be able to call that function from a base class pointer with different parameters, depending on what the derived type is. Something functionally similar to the following wildly illegal example:
class Base
{
virtual void doThing() = 0;
}
class Derived1 : public Base
{
void doThing(int i, const std::string& s) {} // can't do that
}
class Derived2: public Base
{
void doThing(double d, std::vector<int>& v) {} // can't do that either
}
enum class ID = {
DERIVED1,
DERIVED2
}
std::map<ID, std::unique_ptr<Base> thingmap = { ... }
std::unique_ptr<Base>& getThing(int) { return thingmap[i] };
int main(int I, const char* argv[]) {
auto baseptr = getThing(DERIVED1);
baseptr->doThing(42, "hello world");
}
I don't want the caller to have to know what the derived type is, only that a Derived1 takes an int and a string. Downcasting isn't an option because the whole point of this is that I don't want the caller to have to specify the derived type explicitly. And C-style variable argument lists are yucky. :-)
Edited to clarify: I know exactly why the above can't possibly work, thank you. :-) This is library code and I'm trying to conceal the internals of the library from the caller to the greatest extent possible. If there's a solution it probably involves a variadic template function.
You can't do that.
Your map is filled with Base instances, so the class DO NOT have the required prototypes implemented in Derived1 or Derived2... And redefining overloaded methods do not implement the pure virtual method doThing, so Derived1 and Derived2 are still abstract classes and therefore cannot be instanciated.
Worst, your getThing function only deals with Base, so the compiler would NEVER allows you to use the overloaded signatures, since they don't exist AT ALL in Base. There is nothing to know the real class behind, since you don't use templates and implicit template argument deduction.
Your pattern cannot be done this way, period. Since you don't want to use neither downcasting nor explicitely specified child classes, you're stuck.
Even if you add all possible prototypes in Base, since it will be pure virtual methods, both derived classes will still be abstract classes. And if they aren't, then you'll never be able to know which one is a NOP and which one is implemented, since it will requires downcasting!
I think that you made a common mistake, even done by expert developers sometimes: you went into conception directly, BEFORE determining your real ROOT needs.
What you ask looks like the core system of a factory, and it's really not the good way to implement this design pattern and/or designing the specialized derived classes.
I have three classes of objects:
class Foo: has a mesh, and I need to get that mesh;
class Bar: is a Foo, but has some further capabilities which Foo doesn't have;
class Baz: is a Foo, but has another completely independent set of capabilities which neither Foo nor Bar have.
All three classes need to have a way to give me their mesh which, however, can be implemented in many ways, of which I need (at the moment I can't see another way) to use at least 2 different ones, which are MeshTypeA and MeshTypeB.
I would like to have a common interface for different implementations of the same concept (getMesh), however, I can't use auto in a virtual method. I'm lacking the facility to make the code have sense. I would like to have:
class Foo
{
public:
virtual ~Foo() = 0;
virtual auto getMesh() const = 0; // doesn't compile
};
class Bar : public Foo
{
public:
virtual ~Bar() = 0;
virtual auto getMesh() const = 0; // doesn't compile
// other virtual methods
};
class ConcreteFooWhichUsesA : public Foo
{
public:
ConcreteFooWhichUsesA();
~ConcreteFooWhichUsesA();
auto getMesh() const override {return mesh_;};
private:
MeshTypeA mesh_;
};
class ConcreteBarWhichUsesB : public Bar
{
public:
ConcreteBarWhichUsesB();
~ConcreteBarWhichUsesB();
auto getMesh() const override {return mesh_;};
// other implementations of virtual methods
private:
MeshTypeB mesh_;
};
MeshTypeA and MeshTypeB are not exclusive to Foo, Bar, or Baz, which is to say all three could have both types of mesh. However I really don't care for which MeshType I get when I later use it.
Do I need to wrap MeshTypeA and MeshTypeB in my own MeshType? Is it a matter of templating the MeshType? I believe there is a way, however related questions aren't helping or I can't formulate my question in a meaningful enough way.
I have also found this where the author uses a Builder class and decltype, but I don't have such a class. Maybe that would be it? Do I need a MeshLoader sort of class as an indirection level?
If your MeshTypes all have a common (abstract) base class, then you can just return (a pointer or reference to) that in the virtual function defintions, and the derived classes can then return their concrete mesh types, and all will be well. If you have code that can work on any mesh type, it is going to need that abstract base anyways.
If your MeshTypes do not all have a common base class, why even have a getMesh method in Foo at all? Remove it and give each of the concrete classes it's own getMesh method that doesn't override (and has nothing in particular to do with the meshes in any other concrete class).
A function's return type is part of its interface. You can't just change it willy-nilly. More specifically, you cannot have a base class virtual method return one thing while an overridden version returns another. OK, you can, but only if the derived version's return type is convertible to the base class return type (in which case, calling through the base class function will perform said conversion on the overriding method's return type).
C++ is a statically typed language; the compiler must know what an expression evaluates to at compile time. Since polymorphic inheritance is a runtime property (that is, the compiler is not guaranteed to be able to know which override will be called through a base class pointer/reference), you cannot have polymorphic inheritance change compile-time constructs, like the type of a function call expression. If you call a virtual method of a base class instance, the compiler will expect this expression to evaluate to what that base class's method returns.
Remember: the point of polymorphic inheritance is that you can write code that doesn't know about the derived classes and have it still work with them. What you're trying to do violates that.
This question is the equivalent of Java's How to make Superclass Method returns instance of SubClass
Suppose this class hierarchy:
class A
{
public:
A makeCopyOfObject();
};
class B: public A
{
public:
void doSomethingB();
};
class C: public A
{
public:
void doSomethingC();
};
I'd like to use it this way:
B().makeCopyOfObject().doSomethingB();
C().makeCopyOfObject().doSomethingC();
But of course I can't, because the makeCopyOfObject function returns an instance of A, not an instance of a subclass.
I surely could write two versions of the function in the two subclasses, but the code would be the same, except for the return type, because all fields to be copied and modified are in the base class. So, is there an alternative?
I don't understand what you try to achieve with that and it is probably not an answer (see comments), but what you can do is a template (in detail a Curiously recurring template pattern).
template<typename CRTP>
class A {
public:
CRTP& makeCopyOfObject() {
return static_cast<CRTP&>(*this);
}
};
class B: public A<B> {
public:
void doSomethingB();
};
class C: public A<C> {
public:
void doSomethingC();
};
And use it as you wanted:
b.makeCopyOfObject().doSomethingB();
c.makeCopyOfObject().doSomethingC();
See running example here.
Sidenote:
Because of laziness, even the function is called makeCopyOfObject it does not create a copy, but returns a reference to the object. To do a copy you have to implement copy constructors and return a copy (search for clone pattern).
It's difficult to see any practical use case for this, but it's easy to do with a non-member function template:
template< class Type >
auto copy_of( Type const& o )
-> Type
{ return o; }
Then you can write
copy_of( B() ).doSomething();
to your hearts' content, instead of just writing
B().doSomething();
Enjoy.
For the academic issue of covariant methods, there is a lot to be said. You might check out answers to how to implement a clone method. Essentially, this is not supported by C++ except for type system support for reference or pointer result, so one must do it "manually", and the three common approaches are (1) fully manual implementation in each class, (2) using a macro that expands to necessary code in each class, and (3) a middle-man class that forwards arguments to base class constructors. With C++03 the third way was about the same order of difficulty as leveraging dominance in a virtual inheritance hierarchy, so with C++03 that was also an option to be mentioned. But it's just not in the right ballpark of practicality with C++11 and later, (1), (2) and (3) it is.
First, beware of slicing.
Second, if you want to make a copy of an object, may I suggest
the copy-constructor:
B b1{};
B b2{b1}.doSomethingB();
or even:
B{ B{} }.doSomethingB();
Also, if you want to preserve polymorphic behaviour, always
handle polymorphic classes via smart-pointers or references.
Note that C++ has value-semantics, while Java has reference-semantics, so design-patterns that are good for Java are not necessarily good for C++.
Being new to C++, I have trouble understanding a linkage problem I'm having. The following is the file that's giving me a headache:
#pragma once
#include <string>
#include "finite_automaton.h"
template<typename RL>
class RegularLanguage {
public:
bool empty();
RegularLanguage<RL> minimize();
RegularLanguage<RL> complement();
RegularLanguage<RL> intersectionWith(RegularLanguage<RL> other);
RegularLanguage<RL> unionWith(RegularLanguage<RL> other);
RegularLanguage<RL> concatenate(RegularLanguage<RL> other);
RegularLanguage<RL> kleeneStar();
/*
* Returns a regular expression that describes the language of this automaton.
*/
std::string string();
bool disjoint(RegularLanguage<RL> other) {
return intersectionWith(other).empty();
}
bool containedIn(RegularLanguage<RL> super) {
return intersectionWith(super.complement()).empty();
}
bool contains(RegularLanguage<RL> sub) {
return complement().intersectionWith(sub).empty();
}
bool equals(RegularLanguage<RL> other) {
return contains(other) && containedIn(other);
}
};
When I compile the project, I get the following errors during the linking phase:
undefined reference to `RegularLanguage<FiniteAutomaton>::complement()'
undefined reference to `RegularLanguage<FiniteAutomaton>::intersectionWith(RegularLanguage<FiniteAutomaton>)'
undefined reference to `RegularLanguage<FiniteAutomaton>::empty()'
both for RegularLanguage<RL>::containedIn(..) and RegularLanguage<RL>::contains(..).
What am I doing wrong? I do get some related errors pertaining to the classes that implement this template class, but I left them out so as not to post unnecessarily much code.
So to summarize what you're trying to do, you have a class template:
template<typename RL> class RegularLanguage {...};
with some methods implemented and others only declared, but not implemented. Then you try to derive from this and in the derived class implement those other methods that weren't implemented in RegularLanguage:
class FiniteAutomaton : public RegularLanguage<FiniteAutomaton>
You seem to be conflating two concepts in C++: inheritance (specifically, polymorphism) and templates.
Your assumption was that by inheriting from RegularLanguage you can implement the missing stuff in the derived class. That's not how templates work, but polymorphism does work that way. You need to either:
Fully implement all methods in the class template RegularLanguage, and then derive FiniteAutomaton from that.
Make RegularLanguage an abstract base class -- not a class template -- with (possibly pure) virtual methods, and derive from that. The methods you want to be implemented in FiniteAutomaton can be. Those may or may not be pure. The methods you don't want to implement in the base class should be declared as pure (=0), and then implemented in the derived class.
It sounds to me like what you're really trying to do would be better accomplished with #2, so here's an incomplete example of how to do that:
class RegularLanguage {
public:
virtual RegularLanguage* Clone() = 0; // Creates a copy of this object
virtual RegularLanguage& complement() = 0; // pure virtual must be implemented in derived class
virtual bool containedIn(RegularLanguage& super) // non-pure, does not have to be implemented in derived
{
return intersectionWith(super.complement()).empty();
}
virtual ~RegularLanguage() {}
};
class FiniteAutomaton
:
public RegularLanguage
{
public:
RegularLanguage* Clone()
{
RegularLanguage* clone = new FiniteAutomaton (*this);
return clone;
}
RegularLanguage* complement()
{
RegularLanguage* comp = this->Clone();
comp->SetSomeStuff();
return comp;
}
};
There are a number of details hidden up there that I haven't mentioned. For one, the return type of complement is now a RegularLanguage pointer, rather than a RegularLanguage by-value. This is required1 in order to avoid the so-called Slicing Problem which would break polymorphism.
For another, I have abandoned the use of templates here because as I've implemented this, there is no apparent need for them. However the use of templates and polymorphism are not completely mutually exclusive. The base class could employ templates, and in fact the base class could be a class template and still be an abstract base class. But the derived class must derive from a concrete instantiation of that base class template. Things get somewhat complicated here. Just be careful that you're not seeing everything as a nail and get carried away with that hammer.
For another, I didn't implement a virtual destructor in the base class before (this is fixed now) but you must2. Just remember this: if a class is intended to be derived from, it should have a virtual destructor in virtually every case.
For another, I've added a Clone method to the base class as a pure virtual. This was in response to the suggestion that complement() shouldn't return this instance of the object, but a new instance which is the complement of this instance. In a polymorphic hierarchy, when we make copies of object we almost always need to do so through the base class pointer, so a Clone() type method is usually present in such a design.
1 "This is required [passing by pointer]: Actually, you could return a reference as well. Return a reference if you can, but here we need to return a pointer. (Actually we should be returning smart pointers, but that's a tangent.)
2 "You must [implement a virtual destructor]: Technically, you need to have a virtual destructor if you intend to delete the object through a base class pointer. I have never in my professional career seen an instance where I could not or should not implement a virtual destructor in the base class of a polymorphic hierarchy. It's close to correct to say you should always do this, even if you have no plans to delete through a base class pointer.
You need to declare bool empty() (and others not implemented in the base) as a pure virtual in the base class:
virtual bool empty() = 0;
and then override/implement them in a descendant class like this:
virtual bool empty(){
...
}
There is a series of problems with this code. The most obvious one has been pointed out: you need your functions pure virtual. But that's just the beginning.
When you make your functions pure virtual, you will immediately notice that the code does not compile any more. The tools will tell you that you cannot instantiate an abstract class. The reason is that you return objects of type ReguarLanguage<...> from your functions by value, thereby invoking the Curse of Object Slicing (look it up). The inability to instantiate an abstract class is just manifestation of Object Slicing.
In order to dispel the dreaded curse, you will have to do the Rite of Return by Pointer, and thereby invoke the lesser curse of Manual Memory Management (this is relatively easily defeated with a bit of Smart Pointer Magic these days).
But you are not only returning languages, you are also accepting them as arguments. Here you need a simpler incantation of Passing by Reference, which does not require any manual memory management. It looks like in your case you can implement the intersection and all the other things by using just the public interface of the "other" argument, so this simple change should suffice.
Oh, and don't forget the virtual destructor. Never forget the virtual destructor... only omit it if you know you don't need it, which is, if your class fits the OO paradigm, never.
If you look at your RegularLanguage class template, you may notice that it never use its template parameter. If this is the case, it can be safely de-templatized. No, wait, it does use the parameter — how else could it create e.g. a complement?
To put it simply, if you have a finite automaton that parses a language, the parser of the complement doesn't have to be a finite automaton. It may contain or reference a FA (or something else!) instead. So you may want to have a subclass of RegularLanguage called Complement that will contain a (polymorphic!) reference to another RegularLanguage — without even having to know what kind of parser is hidden inside that one.
I want to put any kind of Object (Object, Object etc.) into one shared_ptr. So I created base class and use shared_ptr.
But, how can I declare
T getMember();
within the base class so I can call ObjectBase.getMember?
class ObjectBase
{
public:
//virtual getMember HOWTO?
};
template<typename T>
class Object : public ObjectBase
{
public:
Object(T x):member(x) { }
T getMember() { return member; }
private:
T member;
};
You can't. How should such a declaration look, that it can return all kinds of types? It's just not possible. You'd have to cast the ObjectBase* to the correct Object<T>* and then use the getMember function. It's only possible if all T share a common base class, so you could return a pointer to that. But that would put a strict constraint on T.
That cannot be done. The compiler must know upfront how many different virtual functions (and overloads) will be available, but in your case you are considering adding new virtual member functions on demand based on new potential instantiations of the derived type.
In most cases, keeping completely unrelated objects in the same container is not a good design option, but for the few cases where it actually is, you can use variant types (consider boost::any or boost::variant, depending on your actual requirements. That is a bundled up, tested implementation of a variant type that you might be able to directly use.