Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ aggregates have no virtual functions?

Tags:

c++

aggregate

In C++, an aggregate is (taken from 8.5.1p1 of the language spec)

an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).

So, #1 is not an aggregate, but #2 is an aggregate. Why is #1 not an aggregate aswell?

struct A { virtual void bark() { } int a; }; // #1
struct B { A b; }; // #2
like image 716
Johannes Schaub - litb Avatar asked Apr 23 '14 15:04

Johannes Schaub - litb


People also ask

Does C have virtual functions?

Although C doesn't provide native support for virtual functions, you can emulate virtual functions in C if you attend to all the details.

What are aggregates C++?

C++ Aggregation Definition: In C++, aggregation is a process in which one class (as an entity reference) defines another class. It provides another way to reuse the class. It represents a HAS-A relationship association, or it has class and relationship.

Does struct have virtual function?

So, structs can have constructors, destructors, base classes, virtual functions, everything.

Is a struct an aggregate?

A struct is an aggregate data type consisting of one or more other types. struct IntList { int value; struct IntList *next; }; This struct contains an integer and a pointer. value and next are called members of the structure.


2 Answers

Why is #1 not an aggregate aswell?

Because the standard definition of aggregates says that it isn't. The definition says that the class cannot have virtual functions if it is to be considered an aggregate type. That's it. That's the "captain obvious" answer.

Since you quoted the standard definition (and read it, I presume), you know this already, so I must assume that what you are asking is whether there is any fundamental reason why a class with virtual functions cannot be an aggregate type.

Obviously, a class with virtual functions must have it's virtual table pointer (or other mechanism) initialized as part of the compiler-generated constructor. And the only thing that aggregates really provide (in addition to serving as a base definition for PODs and the like) is the ability to do a curly-braced initialization of its data members. I don't see any reason why the compiler could not simply permit the curly-braced initialization syntax while doing the initialization of the virtual table pointer too.

As far as B is concerned, it can be an aggregate because the brace-initialization is possible as long as there is a way to construct the data members from whatever is provided (or not provided) in the initialization list, i.e., it needs each data members to have some (compiler-generated or not) default, copy or move constructor. Remember, the definition of aggregates is shallow as opposed to recursive like the POD definitions (trivial, std-layout), meaning that only the top-level class has those restrictions, not its sub-objects.

The definition of aggregates is obviously very reminiscent of the C struct restrictions, and the brace-initialization for structs is obviously also a feature carried over from C. I believe that for historical reasons, the definition of aggregates was built such that it reflects C structs, and not for reasons of what is or isn't possible for the compiler to do.

I would certainly be of the opinion that there is no good reason for the restriction on aggregates to not have virtual functions. Maybe a proposal should be made to the standard committee to remove this restriction (as it wouldn't break any existing code). Especially now, with unified initialization syntax, aggregates are nothing more than classes where the compiler can generate a constructor with all the data members as parameters (with default values being default-constructed objects). The only other purpose for aggregates is to lump a few of the restrictions that apply to POD classes (trivial, standard-layout, etc.), for which the restriction on not having virtual functions is justified (AFAIK), but that is just a matter of moving that restriction over to PODs.

like image 51
Mikael Persson Avatar answered Nov 03 '22 06:11

Mikael Persson


I can't say for sure what was in the committee's minds when they added that restriction to the definition of aggregates. I suspect that it's because they considered that requiring the compiler to also have to set up an instance for virtual function calls (vtable or other) would be sufficiently different from simply initializing values and so added the restriction to simplify the requirements on language implementors.

like image 26
Mark B Avatar answered Nov 03 '22 07:11

Mark B