9

I'm having a hard time with this concept. What is Stroustrup getting at here? What is special about a class whose "representation is part of its definition"? What does a "concrete type" contrast with? (I assume it contrasts with "abstract type", but since, AFAIK, you can't even bring an instance of an abstract type into existence, it seems obvious you couldn't place that on the stack, initialize it, etc.)

Is there such a thing as a class I could instantiate that would NOT fit this description of a "concrete class"? Normally I find BS very easy to follow, but I'm missing the point here.

The basic idea of concrete classes is that they behave “just like built-in types.” For example, a complex number type and an infinite-precision integer are much like built-in int, except of course that they have their own semantics and sets of operations. Similarly, a vector and a string are much like built-in arrays, except that they are better behaved (§ 4.2, § 4.3.2, § 4.4.1).

The defining characteristic of a concrete type is that its representation is part of its definition. In many important cases, such as a vector, that representation is only one or more pointers to more data stored elsewhere, but it is present in each object of a concrete class.... In particular, it allows us to

• place objects of concrete types on the stack, in statically allocated memory, and in other objects (§ 6.4.2);

• refer to objects directly (and not just through pointers or references);

• initialize objects immediately and completely (e.g., using constructors; § 2.3.2); and

• copy objects (§ 3.3).

Stroustrup, Bjarne (2013-07-10). The C++ Programming Language (4th Edition) (Section 16.3 Concrete Classes; Kindle Locations 2373-2386). Pearson Education. Kindle Edition.

  • 1
    Try another book! I know Stoustrup is the main author of C++ and has a brain the size of a planet etc. etc. but his english prose style is dense and academic to the point of being unreadable. – James Anderson Dec 16 '13 at 1:35
  • 4
    @JamesAnderson Actually, in general, I find his prose surprisingly readable - spare, to the point, written in the first and second person, and almost conversational. :) This was the first place that I got stuck. – Chap Dec 16 '13 at 1:44
  • How about contrasting it with a variable length object. While not strictly 100% C++, it is valid C: struct variable_length { char data[]; }. – Kain0_0 Jun 3 '20 at 9:41
7

You've pretty much got it right, a concrete type is something that you can create an instance of, while an abstract type is not. For example, consider a typical pedagogical hierarchy such as:

class animal {
    virtual void noise() = 0;
}
class dog: public animal {
    void noise() { cout << "bark\n"; }
public:
    human *master;
}
class cat: public animal {
    void noise() { cout << "meow\n"; }
public:
    std::vector<human *> slaves;
}

You can create instances of dog or cat because they are concrete, and not abstract. On the other hand, you can't create an instance of an animal, but only hold a pointer (or refernce) to one. For example:

void hungry(animal *a) {
    a->noise();
}

In terms that Stroustrup is using, the representation of an animal is not included in the definition of class animal. The representation for a particular kind of animal is described in a subclass, here either dog or cat.

  • One of his criteria for a concrete type is that you can create one on the stack. I'm guessing that you can't create an abstract type on the stack because its size can't be determined. (Similarly, I believe, you can't make a container of base class objects - e.g. your animals - and expect to be able to add derived class objects to it, because they'll be truncated [wrong word]). – Chap Dec 16 '13 at 1:37
  • 2
    That's correct. (The word is object slicing). – Greg Hewgill Dec 16 '13 at 7:33
  • "concrete == !abstract" is standard definition from eg. Java, but not exactly what Stroustrup meant. For him concrete class is more like plain data structure + invariant, without OOP staff like inheritance. – artin Feb 7 '19 at 12:43
4

It seems a term used by BS with a meaning which only him is using AFAIK. I'm not sure I understand fully what he intend.

  1. First a citation from the same section:

    Such types are called concrete types or concrete classes to distinguish them from abstract classes and classes in class hierarchies.

    So for him a a non abstract descendant of an abstract class is not a concrete class (which isn't a nuance I'm used to, the familiar usage for me is that all non abstract classes are concrete), at least if than inheritance is not an implementation detail. His concrete classes seems to be standalone utilities.

  2. Another concrete/abstract dichotomy I'm familiar with is for data structure. An abstract data structure is defined by its operation (say a Dictionary provide look up, insertion, ...) A concrete data structure states how those are provided (an hash table for instance). His insistence that representation is exposed is perhaps related to that (probably due to the influence of the representation on complexity).

  3. Stepanov and McJones in Elements of Programming are using a concept of Regular types. Stroustrup is also using that notion (in section 24.3.1) and I'm not sure what the difference is with the concrete types. Two guesses:

    • the concrete type is more a notion of intend of usage than strict properties while the concept of Regular is intended to describe properties that a type has to have to be usable in generic contexts.
    • the notion of regular type is a refinement of the one concrete type and he didn't saw when he introduced it that they should perhaps be unified (the description of concrete types is already present in the second description but seem to have been rewritten).
  • Re (1), the problem with a "non-abstract class in a hierarchy" is that there may be more derived classes inheriting from it. This e.g. complicates the last bullet of Stroustrups list, "copy objects". Re (2), Stroustrup doesn't claim it's exposed, merely that it's fixed. All std::string objects have the same unknown internal representation. That makes value assignment possible. – MSalters Dec 16 '13 at 10:15
1

The following information is from The C++ Programming Language (4th Edition):

§3.2.1 "The defining characteristic of a concrete type is that its representation is part of its definition"

§16.3 "Such types are called concrete types or concrete classes to distinguish them from abstract classes (§20.4) and classes in class hierarchies (§20.3, §21.2)"

§16.3 "A class is called concrete (or a concrete class) if its representation is part of its definition. This distinguishes it from abstract classes (§3.2.2, §20.4) which provide an interface to a variety of implementations."

§16.3.4: "In particular, concrete types are not intended to display run-time polymorphic behavior (see §3.2.3, §20.3.2)" [§3.2.3 and §20.3.2 have the title "Virtual Functions"]

§16.3.4: "Alternatively, the derived class mechanism discussed in Chapter 20 can be used to define new types from a concrete class by describing the desired differences. The definition of Vec from vector (§4.4.1.2) is an example of this. However, derivation from a concrete class should be done with care and only rarely because of the lack of virtual functions and run-time type information (§17.5.1.4, Chapter 22)."

Bjarne Stroustrup sees concrete types as synonymous to value types. With value-oriented-programming differing from certain aspects of object-oriented-programming.

Concrete types show no run-time polymorphic behaviour. So the means to modify the behaviour of concrete types with inheritance is limited. It is allowed that a concrete type aggregates other types as member variables. A concrete type can also inherit from other concrete types. It is also allowed that a concrete type uses the free store (heap) for storing data and access it with pointers.

The deciding property seems to be, concrete types do not have any virtual functions. The opposite types - those with virtual members - are often called polymorphic types (or reference types according to the Microsoft C++ documentation, some other experts define reference types differently), so a concrete type is non-polymorphic.

Abstract types are always polymorphic types, but the reverse is not generally true.

Concrete types are typically (semi- or) regular types, offering the default operations in the Rule of Six.

(However, cppreference defines all instantiable classes (non-abstract classes) as concrete, and concrete classes can inherit from (or be the base of) abstract classes: https://en.cppreference.com/w/cpp/language/abstract_class)

I am not sure, whether BS would see all 'resource types' (e.g. network sockets, files, ..., convered by RAII) as concrete types, even if they are not polymorphic. The resource types often cannot be copied and sometimes need special initialization (non-default constructors or something even more intricate).

I am also not sure, if BS would see final classes with virtual functions or classes with virtual functions that have all been finalized (called devirtualization) as concrete: If you have a variable of this type, you know, which functions are called (the ones defined in the class) - those types no longer show run-time polymorphic behaviour.

Perhaps we should - for the sake of this discussion - distinguish between the actually instantiated class type (dynamic type) and the type, with which we access that class in program code (static type). The properties of concrete classes, as described by BS, can only be realized, if the class type is accessed by its actual type (and not by the type of one of its base classes). So usage patterns matter.

Not the answer you're looking for? Browse other questions tagged or ask your own question.