Multiple inheritance and generic program - c++

I am reading "Modern C++ Design: Generic Programming and Design Patterns Applied" by Andrei Alex., just started. At page 6, it has the following critcism of multiple inheritance:
The problems with assembling separate features by using multiple inheritance are as follows:
...
Type information. The base classes do not have enough type
information to carry out their tasks. For example, imagine you try to
implement deep copy for your smart pointer class by deriving from a DeepCopy
base class. What interface would DeepCopy have? It must create objects of a
type it doesn't know yet.
I am wondering if this particular critique is flawed.
Interface driven design normally has base class a pure virtual class and the child class implements the interfaces. Take DeepCopy as example, I would do this:
struct DeepCopy
{
virtual void copy(DeepCopy *src) = 0;
};
class MyClass : public DeepCopy, public AnotherIntf
{
public:
virtual void copy(DeepCopy *src);
};
In this example, MyClass is the implementer and it is a real class.
Maybe I miss the point of Andrei's critique here.
What do you think?

It was my understanding that Alexandrescu was speaking of an external copying facility here, not an intrusive one that requires modification of the classes being copied. The proper way to implement deep copy for a given class may differ based on the class's implementation, so without a way to provide type information to the external copying facility you can't select the proper approach.
Deep copy may not be a great example here -- his chapters on generalized functors, smart pointers, and multiple dispatch are what I would consider better real-world examples of his policy-based design.

Related

Is Abstract class an example of Abstract data type?

I'm getting confused by these two. What I learned is that Abstract data type is a mathematical model for data type, where it specifies the objects and the methods to manipulate these objects without specifying the details about the implementation of the objects and methods. Ex: an abstract stack model defines a stack with push and pop operations to insert and delete items to and from the stack. We can implement this in many ways, by using linked lists, arrays or classes.
Now, coming to the definition of abstract class, its a parent class which has one or more methods that doesn't have definition(implementation?) and cannot be instantiated (much like we can't implement an abstract stack as it is, without defining the stack's underlying mechanism through one of the concrete data structures). For ex: if we have an abstract class called Mammal which includes a function called eat(), we don't know how a mammal eats because a mammal is abstract. Although we can define eat() for a cow which is a derived class of mammal. Does this mean that mammal serves as an adt and cow class is an implementation of the mammal adt?
Correct me if I'm wrong in any way. Any kind of help would be really appreciated.
Abstract data type is a mathematical model for data type...
Now, coming to the definition of abstract class...
You need to distinguish between theoretical mathematical models and a practical implementation techniques.
Models are created by people in order to reason about problems easily, in some comprehensible, generalized way.
Meanwhile, the actual code is written in order to work and get the job done.
"Abstract data type" is a model. "Abstract class" is a programming technique which some programming languages (C++, C#, Java) support on the language level.
"Abstract data type" lets you think and talk about the solution of a problem, without overloading your brain with unnecessary (at this moment) implementation details. When you need a FIFO data structure, you say just "stack", but not "a doubly-linked list with the pointer to the head node and the ability to...".
"Abstract class" lets you write the code once and then reuse it later (because that is the point of OOP - code reuse). When you see that several types have a common interface and functionality - you may create "an abstract class" and put the intersection of their functionality in inside, while still being able to rely on yet unimplemented functions, which will be implemented by some concrete type later. This way, you write the code once and when you need to change it later - it's only one place to make the change in.
Note:
Although, in C++ ISO Standard (at least in the draft) there is a note:
Note: The abstract class mechanism supports the notion of a general concept,
such as a shape, of which only more concrete variants, such as circle
and square, can actually be used.
but it is just a note. The real definition is:
A class is abstract if it has at least one pure (aka unimplemented) virtual function.
which leads to the obvious constraint:
no objects of an abstract class can be created except as subobjects of
a class derived from it
Personally, I like that C++ (unlike C# and Java) doesn't have the keyword "abstract". It only has type inheritance and virtual functions (which may remain unimplemented). This helps you focus on a practical matter: inherit where needed, override where necessary.
In a nutshell, using OOP - be pragmatic.
The term "abstract data type" is not directly related to anything in C++. So abstract class is one of the potential implementation strategies to implement abstract data types in the given language. But there are a lot more techniques to do that.
So abstract base classes allow you to define a set of derived classes and give you the guarantee that all interfaces ( declarations ) have also an implementation, if not, the compiler throws an error, because you can't get an instance of your class because of the missing method definition.
But you also can use compile time polymorphism and related techniques like CRTP to have abstract data types.
So you have to decide which features you need and what price you want to pay for it. Runtime polymorphism comes with the extra cost of vtable and vtable dispatching but with the benefit of late binding. Compile time polymorphism comes with the benefit of much better optimizable code with faster execution and less code size. Both give you errors if an interface is not implemented, at minimum at the linker stage.
But abstract data types with polymorphism, independend of runtime or compile time, is not a 1:1 relation. Making things abstract can also be given by simply defining an interface which must be somewhere fulfilled.
In a short: Abstract data types is not a directly represented in c++ while abstract base class is a c++ technique.
Is Abstract class an example of Abstract data type?
Yes, but in C++, abstract classes have become an increasingly rare example of abstract data types, because generic programming is often a superior alternative.
Ex: an abstract stack model defines a stack with push and pop
operations to insert and delete items to and from the stack. We can
implement this in many ways, by using linked lists, arrays or classes.
The C++ std::stack class template more or less works like this. It has member functions push and pop, and it's implemented in terms of the Container type parameter, which defaults to std::deque.
For an implementation with a linked list, you'd type std::stack<int, std::list<int>>. However, arrays cannot be used to implement a stack, because a stack can grow and shrink, and arrays have a fixed size.
It's very important to understand that the std::stack has absolutely nothing to do with abstract classes or runtime polymorphism. There's not a single virtual function involved.
Now, coming to the definition of abstract class, its a parent class
which has one or more methods that doesn't have
definition(implementation?) and cannot be instantiated
Yes, that's precisely the definition of an abstract class in C++.
In theory, such a stack class could look like this:
template <class T>
class Stack
{
public:
virtual ~Stack() = 0;
virtual void push(T const& value) = 0;
virtual T pop() = 0;
};
In this example, the element type is still generic, but the implementation of the container is meant to be provided by a concrete derived class. Such container designs are idiomatic in other languages, but not in C++.
much like we can't implement an abstract stack as it is, without defining the stack's underlying mechanism through one of the concrete data structures
Yes, you couldn't use std::stack without providing a container type parameter (but that's impossible anyway, because there's the default std::deque parameter), and you cannot instantiate a Stack<int> my_stack; either.

Mechanics of multiple inheritance compared to templates wrt building flexible designs

This is a narrower version of the question put on hold due to being too broad.
On pages 6-7 of Modern C++ Design, Andrei Alexandrescu lists three ways in which the multiple inheritance is weaker than templates with respect to building flexible designs. In particular, he states that the mechanics provided by multiple inheritance is poor (the text in square brackets and formatting are mine as per my understanding of the context):
In such a setting [i.e. multiple inheritance], [to build a flexible SmartPtr,] the user would build a multithreaded, reference-counted smart pointer class by inheriting some BaseSmartPtr class and two classes: MultiThreaded and RefCounted. Any experienced class designer knows
that such a naïve design does not work.
...
Mechanics. There is no boilerplate code to assemble the inherited components in a controlled
manner. The only tool that combines BaseSmartPtr, MultiThreaded, and RefCounted
is a language mechanism called multiple inheritance. The language applies
simple superposition in combining the base classes and establishes a set of simple rules
for accessing their members. This is unacceptable except for the simplest cases. Most
of the time, you need to orchestrate the workings of the inherited classes carefully to
obtain the desired behavior.
When using multiple inheritance, one can achieve some pretty flexible orchestration by writing member functions that call member functions of several base classes. So, what is the orchestration that is missing from multiple inheritance and present in templates?
Please note that not every disadvantage of multiple inheritance compared to templates goes as an answer here, but only a disadvantage in what Andei calls mechanics in the above quote. In particular, please make sure that you are not talking about one of the other two weaknesses of multiple inheritance listed by Andrei:
Type information. The base classes do not have enough type information to carry on
their tasks. For example, imagine you try to implement deep copy for your smart
pointer class by deriving from a DeepCopy base class. But what interface would DeepCopy
have? It must create objects of a type it doesn’t know yet.
State manipulation. Various behavioral aspects implemented with base classes must manipulate
the same state. This means that they must use virtual inheritance to inherit a
base class that holds the state. This complicates the design and makes it more rigid because
the premise was that user classes inherit library classes, not vice versa.
I think that what Alexandrescu is referring to in the "Mechanics" paragraph is expounded upon in the rest of the chapter. He's referring to how much more flexible policy-based class design is than inheritance-based class design, particularly with respect to the various ways in which policies can be implemented and combined - this in comparison to the single implementation and combination allowed through multiple inheritance.
For instance, when discussing the Creator policy he points out that the policy requires only a Create() method that returns a pointer to the class being created, but doesn't specify that it be virtual or non-static. And he shows several ways in which each policy could be created: a straightforward policy class such as (from section 1.5, skipping the MallocCreator and PrototypeCreator policies)
template<class T>
struct OpNewCreator
{
static T* Create()
{
return new T;
}
};
...
> //Library code
> template <class CreationPolicy>
> class WidgetManager:public CreationPolicy
> {
> ...
> };
...
// Application Code
typedef WidgetManager<OpNewCreator<Widget> > MyWidgetMgr;
or it could be implemented with template template parameters (section 1.5.1) as
//Library Code
template <template <class> class Creation Policy>
class WidgetManager : public CreationPolicy <Widget>
{
...
}
// Application Code
typedef WidgetManager<OpNewCreator> MyWidgetMgr
or (section 1.5.2) - implemented as a template member function:
struct OpNewCreator
{
template <class T>
static T* Create()
{
return new T;
}
}
These are examples of the flexible mechanics that are available in a template-based policy class solution and not available in a multiple inheritance solution. These particular examples are not maybe all that exciting, probably because they have to be short and simple for pedagogical reasons.

Difference between interface and polymorphism [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I was reading an online excerpt from a C++ book on polymorphism and interfaces.
The book made a distinction between polymorphism and interfaces, and specified how to implement them in C++. However, I was always under the idea that interfaces in C++ (implemented using a base class with pure virtual functions) were nothing more than an application of polymorphism.
I would like to know the clear distinction between polymorphism and interfaces because the excerpt confused me.
Polymorphism is the abstract concept of dealing with multiple types in a uniform manner, and interfaces are a way to implement that concept. Code that interacts with an interface can interact with any type that provides that interface.
Note that C++ has (at least) two forms of polymorphism: dynamic (i.e. run-time) polymorphism via interfaces formally defined by virtual functions, and static (i.e. compile-time) polymorphism via interfaces informally defined by the use of template parameters.
Typical C++ interfaces make use of virtual functions and polymorphism to provide the actual implementation. But polymorphism covers many other things, which is "not interfaces".
An interface is a base-class that can be used to a class that is passed back to something that accepts that interface. In some cases, a class may provide more than one interface:
class MyClass: public InterfaceGUI, InterfaceAudio
{
....
};
here, MyClass provides a class that interfaces both with the GUI and the Audio interfaces. This is a one case of multiple inheritance.
On the other hand:
class Animal
{
int numLegs;
public:
Animal(int nLegs): numLegs(nLegs) {}
};
class Dog : public Animal
{
Dog() : Animal(4) { }
};
here Animal is not a pure interface class, since it implements some functionality, and this is generally not a good design for an interface.
What i understood from the concept of polymorphism and Interface is as follows:
Polymorphism :
Polymorphism is nothing but having more than one form(As per all books).
But As per the Object orientation when you relate it with the real life You will get to know that Polymorphism is nothing but having more than one form with same name or some other Quality but have one's own Patent quality which no one have.
As per the programming:
A function with same name But different arguments (Compile time Polymorphism) and a Virtual function used for Runtime Polymorphism As explained here
Check this Example
Interface
An interface describes the behavior or capabilities of a C++ class without committing to a particular implementation of that class.
The C++ interfaces are implemented using abstract classes and these abstract classes should not be confused with data abstraction which is a concept of keeping implementation details separate from associated data.
For this purpose we use Pure Virtual function
For Reference you can go through this Link
And for example you can use explanation by Mats Petersson
Hope this will help you to understand the basic senario.

Use of making the base class polymorphic?

I know the keyword virtual makes the base class polymorphic and if I create an object and call a virtual function, corresponding function will be called based on the run time allocation but why should I create an object with different types. I mean
Base *ptr = new Derived;
ptr->virtualfunction(); //calls the function which has implemented in Derived class.
If I create an object so that
Derived *ptr = new Derived;
ptr->virtualfunction(); // which does the same without the need of making the function virtual.
Because you might want to store objects of different types together:
std::vector<std::unique_ptr<Base>> v;
v.push_back(make_unique(new DerivedA()));
v.push_back(make_unique(new DerivedB()));
v.push_back(make_unique(new DerivedC()));
Now, if you go over that vector:
for (auto& p : v) {
p->foo();
}
It will call foo() of DerivedA, B, and C appropriately.
Let's go with a simple example : Let's say you have
class Base {};
class Derived1 : public Base {};
class Derived2 : public Base {};
Now, let's say you want to be able to store in a vector (or any container) both Derived1 and Derived2 instances.
You have to use the base class in that case.
std::vector<Base*>
// or std::vector<std::unique_ptr<Base>>
The need for polymorphism is the need of processing different data in the same manner. Rather than reimplementing over and over the same algorithm for dataset with different shapes, wouldn't it be much easier to have only one implementation of that algorithm, and parameterize it with different operators?
That's the essence of polymorphism. You start with an algorithm, establish the interface it must interact with, and then build implementations of that interface. In C++ the notion of interface is implicit in every classes. Any class exposes one interface (though it may support many interfaces through its ancestors), and its descendants implement it as well. By making certain methods virtuals, the descendants may override and adapt them to their own internal structures, without modifying how the object is manipulated from the outside.
So polymorphism is really that, values which may adopt different shapes, and the means to access and manipulate them uniformally. The key point in answering your question is perhaps that the algorithm does not know which implepentation it is manipulating. You provide a trivial example where the code knows that it works with an instance of Derived, and thus may call its methods directly. In generic code, or code refering to an interface (so to speak), that knowledge does not exist, which forces the code to rely on the base class methods (and requires the programmer to ensure that the classes he plans to use with that code are well defined - ie. virtual - where needed).
There are many useful applications of polymorphism, but they all derive from the above principle:
heterogeneous dataset (as illustrated by other answers),
injection ( in which different implementations of the same interface may be swapped one for another at runtime),
testing (and more specifically mocking, in which classes which interact with a given class C are replaced by dummies which help test the correct behaviour of C),
to name a few. Note that compile time polymorphism (templates), and runtime polymorphism (virtual methods and inheritance) both achieve that goal, albeit in a different way, and with different pros and cons.

Base class "Object", lazy/smart or stupid?

What I'm wondering is: if having a base class, that every* other class inherits from is a good idea or not in C++. Basically, it has the same interface as C#'s Object, which is:
*except for straight interfaces and data structures
class Object
{
public:
virtual ~Object() {}
virtual std::string toString() const = 0;
virtual Object* copy() const = 0;
virtual void release() = 0;
private:
// This operator overload calls toString() to print it out to the stream.
friend std::ostream& operator<<(std::ostream& output, const Object& object);
};
Is this a good thing to do, or am I better off just making seperate interfaces if I want the class to be copied, or converted to a string.
For example
class Copyable
{
public:
virtual ~Copyable() {}
virtual Copyable* copy() const = 0;
};
I'm not sure about this at all, and it's doing my head in. :(
I wouldn't do it. Your Object forces each and every class to implement those pure virtual methods. What if you don't really need them?
C++ has multiple inheritance, so you can have a separate class for each purpose, and let the derived classes decide which traits do they need.
Having those virtual function also adds an overhead, as it adds a vptr to every instance of every class. Might not have a horrible effect, but it's not the C++ spirit IMO.
Lastely, C# and Java's Object have some useful methods because they have a lot more information on the type at runtime. This makes having a single root for all types reasonable. Some C++ frameworks have it as well (MFC's CObject comes to mind), but providing useful facilities at that level is not trivial in C++. You'll have to do more than just offer pure virtual methods - the major gain from having a single root is getting shared implementation via inheritance, not polymorphism. Using your Object in a polymorphic manner just breaks static typing, and in your case, you don't even get any code reuse.
C++ does not have common base class for all objects primarily for perf reasons, especially because of the VMT (virtual methods table). VMT is a pointer that is present in every object that has at least one virtual method. Authors of C++ wanted to support simple objects (with body consisting of one int for example). This is valid and reasonable goal.
This only works if enforced at the language level (as in Java.) In C++ you'd have to deal with non-Object objects anyway. There is no way to force libraries to inherit from Object. Once you instantiate anything from std::, you have a non-Object object in your code.
It is difficult to give a one size fits all answer.
Think through what benefits it is going to give you.
Now think through how much extra work it is going to cause e.g. multiple inheritance complications etc.
Generally doing this is going to be more work than not doing it so you need to make sure that it is going to give you a substantial benefit or you are wasting time.