Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I inherit from int in C++?

I'd love to be able to do this:

class myInt : public int {  }; 

Why can't I?

Why would I want to? Stronger typing. For example, I could define two classes intA and intB, which let me do intA + intA or intB + intB, but not intA + intB.

"Ints aren't classes." So what?

"Ints don't have any member data." Yes they do, they have 32 bits, or whatever.

"Ints don't have any member functions." Well, they have a whole bunch of operators like + and -.

like image 743
Rocketmagnet Avatar asked Jan 26 '10 22:01

Rocketmagnet


People also ask

Which Cannot be inherited in C?

A Static class and a Sealed class cannot be inherited. Sealed class cannot be inherited. Class that are marked with the sealed (C#) or NotInheritable (VB.NET) keywords cannot be inherited from. This is done at the definition of the classes.

Is inheritance possible in C?

No it doesnt. C is not an Object Oriented language. Inheritance is a property of OO languages.

Can you inherit an STD?

Some STIs, such as syphilis, cross the placenta and infect the baby in the womb. Other STIs, like gonorrhea, chlamydia, hepatitis B, and genital herpes, can pass from the mother to the baby as the baby passes through the birth canal.

Which functions Cannot be inherited in C++?

C++ - Constructor & Friend Function Constructor cannot be inherited but a derived class can call the constructor of the base class. In C++, friend is not inherited. If a base class has a friend function, then the function does not become a friend of the derived class(es).


1 Answers

Neil's comment is pretty accurate. Bjarne mentioned considering and rejecting this exact possibility1:

The initializer syntax used to be illegal for built-in types. To allow it, I introduced the notion that built-in types have constructors and destructors. For example:

int a(1);    // pre-2.1 error, now initializes a to 1 

I considered extending this notion to allow derivation from built-in classes and explicit declaration of built-in operators for built-in types. However, I restrained myself.

Allowing derivation from an int doesn't actually give a C++ programmer anything significantly new compared to having an int member. This is primarily because int doesn't have any virtual functions for the derived class to override. More seriously though, the C conversion rules are so chaotic that pretending that int, short, etc., are well-behaved ordinary classes is not going to work. They are either C compatible, or they obey the relatively well-behaved C++ rules for classes, but not both.

As far as the comment the performance justifies not making int a class, it's (at least mostly) false. In Smalltalk all types are classes -- but nearly all implementations of Smalltalk have optimizations so the implementation can be essentially identical to how you'd make a non-class type work. For example, the smallInteger class is represents a 15-bit integer, and the '+' message is hard-coded into the virtual machine, so even though you can derive from smallInteger, it still gives performance similar to a built-in type (though Smalltalk is enough different from C++ that direct performance comparisons are difficult and unlikely to mean much).

The one bit that's "wasted" in the Smalltalk implementation of smallInteger (the reason it only represents 15 bits instead of 16) probably wouldn't be needed in C or C++. Smalltalk is a bit like Java -- when you "define an object" you're really just defining a pointer to an object, and you have to dynamically allocate an object for it to point at. What you manipulate, pass to a function as a parameter, etc., is always just the pointer, not the object itself.

That's not how smallInteger is implemented though -- in its case, they put the integer value directly into what would normally be the pointer. To distinguish between a smallInteger and a pointer, they force all objects to be allocated at even byte boundaries, so the LSB is always clear. A smallInteger always has the LSB set.

Most of this is necessary, however, because Smalltalk is dynamically typed -- it has to be able to deduce the type by looking at the value itself, and smallInteger is basically using that LSB as a type-tag. Given that C++ is statically typed, there's never a need to deduce the type from the value, so you probably wouldn't need to "waste" that bit on a type-tag.


1. In The Design and Evolution of C++, §15.11.3.

like image 188
Jerry Coffin Avatar answered Oct 09 '22 00:10

Jerry Coffin