What Does Multiple Class Definition Mean and How Is It Supposed to Work

What does multiple class definition mean and how is it supposed to work?

It is the hierarchical selector.

.ui-widget-content .ui-state-default

Means select all those child elements with the class ui-state-default whose parent has the class ui-widget-content.


I am writing an example for you to grasp it by seeing it in action.

1. Markup

<div class="ui-tabs">
<div class="ui-widget-content">
<div class="ui-state-default"></div>
<div class="ui-state-default"></div>
<div></div>
</div>
</div>

<div class="ui-button">
<div class="ui-widget-content">
<div class="ui-state-default"></div>
<div class="ui-state-default"></div>
<div></div>
</div>
</div>

2. CSS

.ui-widget-content .ui-state-default{
background-color: red;
border: 1px solid black;
display: block;
height: 100px;
width: 100px;
}

.ui-button .ui-widget-content .ui-state-default{
background-color: green;
border: 3px dashed yellow;
}

3. Explanation

All DIVs with the class ui-state-default that have a parent with the class ui-widget-content will have applied all the properties of the first CSS rule, except those DIVs whose parent has the class ui-parent, whose background-color rule will be overwritten.

Why is there no multiple definition error when you define a class in a header file?

The one-definition rule (3.2, [basic.def.odr]) applies differently to classes and functions:

1 - No translation unit shall contain more than one definition of any variable, function, class type, enumeration type, or template.

[...]

4 - Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program [...]

So while (non-inline) functions may be defined at most once in the whole program (and exactly once if they are called or otherwise odr-used), classes may be defined as many times as you have translation units (source files), but no more than once per translation unit.

The reason for this is that since classes are types, their definitions are necessary to be able to share data between translation units. Originally, classes (structs in C) did not have any data requiring linker support; C++ introduces virtual member functions and virtual inheritance, which require linker support for the vtable, but this is usually worked around by attaching the vtable to (the definition of) a member function.

Why does the same class being defined in multiple .cpp files not cause a linker multiple definition error?

You're thinking of the one definition rule. I'm quoting from there (boldface is emphasis of my choosing, not a part of the original document).

Your understanding would be correct--it's illegal to define the same function in multiple compilation units:

One and only one definition of every non-inline function or variable that is odr-used (see below) is required to appear in the entire program (including any standard and user-defined libraries). The compiler is not required to diagnose this violation, but the behavior of the program that violates it is undefined.

However, this isn't the case for classes, which can be defined multiple times (up to once in each compilation unit), as long as the definitions are all identical. If they are identical, then you can safely pass instances of that class from one compilation unit to another, since all compilation units have compatible, identical definitions with compatible sizes and memory layouts.

Only one definition of any variable, function, class type, enumeration type, concept (since C++20) or template is allowed in any one translation unit (some of these may have multiple declarations, but only one definition is allowed).

...

There can be more than one definition in a program, as long as each definition appears in a different translation unit, of each of the following: class type, enumeration type, inline function with external linkage inline variable with external linkage (since C++17), class template, non-static function template, static data member of a class template, member function of a class template, partial template specialization, concept, (since C++20) as long as all of the following is true:

  • each definition consists of the same sequence of tokens (typically, appears in the same header file)
  • name lookup from within each definition finds the same entities (after overload-resolution), except that constants with internal or no linkage may refer to different objects as long as they are not ODR-used and have the same values in every definition.
  • overloaded operators, including conversion, allocation, and deallocation functions refer to the same function from each definition (unless referring to one defined within the definition)
    the language linkage is the same (e.g. the include file isn't inside an extern "C" block)
  • the three rules above apply to every default argument used in each definition
  • if the definition is for a class with an implicitly-declared constructor, every translation unit where it is odr-used must call the same constructor for the base and members
  • if the definition is for a template, then all these requirements apply to both names at the point of definition and dependent names at the point of instantiation

If all these requirements are satisfied, the program behaves as if there is only one definition in the entire program. Otherwise, the behavior is undefined.

The bullet points are a fancy and highly precise way of specifying that the definitions must be the same, in letter and in effective result.

Do I correctly understand what a class is?

A class is a kind of thing, an object is an actual thing. So, in the real world, "person" is a class, you and I are objects (or instances) of that class. "Car" is a class, my 1996 beater Volvo station wagon is an object.

Objects all have certain similarities in form and function because of the class they belong to. When I say my station wagon is a "car", you have a pretty good idea of what it looks like, what it's used for, and what it can do. But objects of a class can also differ from each other. Just because something's a car doesn't tell you exactly what shape it is or how many seats it has or what color it is.

In the example you gave, it's likely that the yes and no buttons are both objects of the class "button" (or some similar name) and that the differences in their behavior are due to changes added by the programmer without his or her bothering to create a new class. However, it is possible that the programmer made the decision to make each type of button a subclass of the original class "button".

What's a subclass? Well, if you think of "car" as a class, it is obvious that there are several intermediate "kinds" of things between "car" and "Larry's 1996 beater Volvo station wagon". These could be "station wagon" and "Volvo station wagon". So my car would be an instance of "Volvo station wagon" which itself would be subclass of "station wagon" which would be a subclass of "car". From the "car" part, we know a good deal about my object, from the "station wagon" part we learn a little more, and from the "Volvo station wagon" a little more still.

The way in which classes and subclasses are arranged is a decision made by the programmer. In my example above, another programmer might have made the classes "car", "Volvos", "pre-Ford", and "Wagons". It depends on the problem you're trying to solve.

C++ Error: Multiple definitions of class functions

You're breaking the One Definition Rule; defining the function in the header means there's a definition in every translation unit that includes the header, and you're usually only allowed a single definition in the program.

Options:

  • Move the function definition into a source file, so there's just one definition; or
  • Add inline to the function definition, to relax the rule and allow multiple definitions; or
  • Define the function inside the class, which makes it implicitly inline. (To answer your final question, yes that is legal.)

Also, don't use reserved names like __GLWidget_h__.

Java: Multiple class declarations in one file

My suggested name for this technique (including multiple top-level classes in a single source file) would be "mess". Seriously, I don't think it's a good idea - I'd use a nested type in this situation instead. Then it's still easy to predict which source file it's in. I don't believe there's an official term for this approach though.

As for whether this actually changes between implementations - I highly doubt it, but if you avoid doing it in the first place, you'll never need to care :)

Is it a bad practice to have multiple classes in the same file?

I think you should try to keep your code to 1 class per file.

I suggest this because it will be easier to find your class later. Also, it will work better with your source control system (if a file changes, then you know that a particular class has changed).

The only time I think it's correct to use more than one class per file is when you are using internal classes... but internal classes are inside another class, and thus can be left inside the same file. The inner classes roles are strongly related to the outer classes, so placing them in the same file is fine.

Is it possible to define multiple classes in just one .cpp file?

There is no rule you have to follow (like in java). You're free to place and name classes in however named files you like (besides the suffix).

However its another question if that is good practices (its not!).

Multiple classes in a header file vs. a single header file per class

The term here is translation unit and you really want to (if possible) have one class per translation unit ie, one class implementation per .cpp file, with a corresponding .h file of the same name.

It's usually more efficient (from a compile/link) standpoint to do things this way, especially if you're doing things like incremental link and so forth. The idea being, translation units are isolated such that, when one translation unit changes, you don't have to rebuild a lot of stuff, as you would have to if you started lumping many abstractions into a single translation unit.

Also you'll find many errors/diagnostics are reported via file name ("Error in Myclass.cpp, line 22") and it helps if there's a one-to-one correspondence between files and classes. (Or I suppose you could call it a 2 to 1 correspondence).

C++ Multiple classes with same name

The standard way around this problem is to wrap the classes in different namespaces.



Related Topics



Leave a reply



Submit