In Java all containers are in a hierarchy of abstract base classes:
List<String> v1 = new LinkedList<String>();
AbstractSequentialList<String> v2 = new LinkedList<String>();
Is there an analogue for SequenceContainer and std::vector in C++?
No, std::vector has no (standard, documented) base class, nor does it have any virtual methods. The C++ standard library doesn't use runtime polymorphism much aside from the iostream classes.
The C++ standard library is geared more towards static, compile-time polymorphism with templates. SequenceContainer is just a name for the way some set of classes can be interacted with. The intent is that you can write template code that interacts with objects only by that documented interface and it will work with any class that fulfills those requirements.
Related
When and Why to use abstract classes/methods?
When creating a class library which will be widely distributed or reused—especially to clients, use an abstract class in preference to an interface; because, it simplifies versioning. This is the practice used by the Microsoft team which developed the Base Class Library. ( COM was designed around interfaces.) Use an abstract class to define a common base class for a family of types. Use an abstract class to provide default behavior. Subclass only a base class in a hierarchy to which the class logically belongs.
I did not understand the explanation in the above quote. Please explain why should an abstract class be used for creating a class library?
You should read articles of such kind very carefully. As I Understood, the main part of article is dedicated to c# language. In terms of such language there is big difference between interfaces and abstract classes. For example, interfaces in terms of c# language is just set of "pure" virtual methods (they cannot have definition within interface, only classes can implement it). Interfaces cannot have constructors. Abstract classes can have constructors. Moreover, c# does not support multiple inheritance ( as opposite to c++ language). In such way, c# interfaces and abstract classes look very different than c++'s one
It might be a silly question but I never saw a question about it or read about it.
Imagine that we have this:
class Numeric
{
public:
virtual ~Numeric() {}
virtual int getNumeric() const = 0;
};
This is considered an interface.
And now I insert an enumerator (It can be something else, like a typedef, etc.)
class Numeric
{
public:
enum Numbers
{
One,
Two,
};
virtual Numbers getNumeric() const = 0;
};
Still being an interface or it is now considered an abstract class?
As I said, it might be silly but I really wonder to know that.
If you are looking for an official answer, then I'm afraid there is none.
The draft of the C++11 standard I am having here merely says [10.4 class.abstract]:
An abstract class can also be used to define an interface for which
derived classes provide a variety of implementations.
All other instances of the word "interface" in the entire ~1300 pages PDF only refer to generic programming or other things not related to OOP or abstract classes.
For example this one here [24.2.1 iterator.requirements.general]:
Most of the library’s algorithmic templates that operate on data
structures have interfaces that use ranges.
This obviously has nothing to do with abstract classes.
Bjarne Stroustrup himself, if you accept his words as "half-official", doesn't really help you in this regard, either. Quoting from the glossary on his homepage:
abstract class - a class defining an interface only; used as a base
class.
You will have to live with the fact that the C++ language itself as well as C++ developers and experts use the word "interface" as a superset for "abstract class". Unlike e.g. in Java, where interfaces are an actual language element with its own interface keyword, there is no such thing in C++.
Everything else is opinion-based.
Your second class Numeric is an interface.
If a class has one or more pure virtual functions, then this class is called an "abstract class".
Generally, if all of a classes' functions are pure virtual functions, then this class is called an "interface".
C++ does not have an explicit interface concept, so the above two classes are called the interface or abstract class, somewhat interchangably.
In my opinion, your second class can be considered an interface. I don't think there is a standard which defines interfaces in C++. However in languages which have interfaces, for example, Java, you can usually have enums defined inside an interface.
I would consider a class with no implementation to be an interface.
I've been wondering, is there any reason for the design decision in C++ to not have a pure abstract class for any of the std library containers?
I appreciate that hash_map came later from the stdext namespace but shares a very similar interface. In the event that I later decide I would like to implement my own map for a particular piece of software, I would have preferred to have some kind of interface to work with.
Example
std::base_map *foo = new std::map<std::string, std::string>;
delete foo;
foo = new stdext::hash_map<std::string, std::string>;
Obviously the above example is not possible, as far as I am aware, however this is similar for list and other std lib containers.
I appreciate that this is not C# or Java, but there is obviously no constraints in C++ to stop this design, so why was it designed like this so that there is no coupling between similar containers.
Because virtual functions add overhead.
Because the containers don't all have the same interface, there are common functions but also important differences regarding iterator invalidation and memory allocation (and so exception behaviour) which you need to understand, if you were using an abstract base you wouldn't know the specifics of how the concrete container would behave.
If you want to write code that is agnostic about the type of container it is passed then in C++ you write a template instead of relying on abstract interfaces, i.e. use static polymorphism not dynamic polymorphism. That avoids the overhead of dynamic dispatch and also allows specialization based on concrete type, because the concrete type is known at compile time.
Finally, it wouldn't have any advantage IMHO. It's better the way it is. As you say, this isn't C# or Java, thankfully.
(P.S. the stdext namespace is not part of C++, it appears to be Microsoft's namespace for non-standard types, a better example would use std::tr1::unordered_map or std::unordered_map instead of stdext::hash_map)
I would like to write a "versatile" class representing the general container storing pointers. Should I use public inheritance or containment?
template <class T>
class List : public std::vector <T *>
{
//...
}
Or
template <class T>
class List
{
private:
std::vector <T *> items;
//...
}
May some problems occur with abstract classes (i.e. virtual destructor)?
If neither proposal is appropriate, what design should I follow (and could you include a short example)?
This is already done for you with Boost's pointer containers.
I do not like boost so I would like to use only C++ 0x00 standard :-).
— Ian (comment)
If you still want to re-invent these classes, look at the design decisions they made. In particular, they don't inherit from other containers as your first code does.
In fact, just copy the code right out from Boost. This is a header-only library and should be straight-forward (i.e. few implementation-specific workarounds). Boost's license is very liberal, not even requiring you to mention Boost when distributing compiled programs.
How about:
typedef std::vector<boost::shared_ptr<T> > List;
That is, I think it's better to use a resource managing pointer within regular container classes than to reinvent each of the container classes to add resource management capability.
private inheritance is a common tactic for creating classes that are implemented in terms of another. Code that uses the class can't tell that the derived class is derived from a private base, so you won't end up in the sorts of situations that might ordinarily require a virtual destructor.
Use using to import members from the private base to the derived class. For example:
template<class T>
class List:
private std::vector<T>
{
public:
using std::vector<T>::operator[];
using std::vector<T>::size;
};
This is a bit crude, but it gives you some flexibility. You can start out by using private inheritance, and this saves you some typing compared to writing forwarding functions, but you can still write alternative implementations long-hand as required. And then, if/when this becomes inappropriate, you can change the implementation style -- perhaps have a vector as a member, for example, or maybe do everything by hand -- safe in the knowledge that client code won't need to change.
This is ideal for situations where you're pretty sure you'll eventually need a non-standard type of container, but have an existing container type that mostly fits the bill for now. And it's a better medium-term solution than a typedef, because there's no risk of client code accidentally (or on purpose...) using the two types interchangeably.
I hope this question is not too silly, but what is the most basic class in standard C++?
object? Object?
class MyObject : public object{ ...
and I get "Expected class-name before token{"
Is there any map, diagram or image that shows standard c++ classes inheritance?
Something like this but for C++ ?
There is no most basic class in C++ i.e. there is no common base class for all the classes.
There is no fundamental object type in C++, unlike in e.g. Java.
In Cocoa, the NSObject class is fundamental to the framework but not to the Objective-C language itself. In Objective-C, it is possible to create a root class by not deriving from anything (but in order to make it work you'll probably have to hack your way through runtime calls).
Similarly, some C++-based frameworks may define a root class that all other classes in that framework derive from, but it is specific to the framework, not the language.
This is the simplest most basic class you can compile:
class Null
{
};
Inheritance diagram for IOstream library is here. STL is a template library and doesn't use OOP.