C++ is mainly an extension of C. Originally C++ was called “C with classes”, highlighting the main original language extension. Already at that time overloading of functions was supported. Since then C++ has acquired exceptions, hierarchical namespaces, generic programming in the form of templates, and lastly multi-threading support. As of C++11 there’s also some minimal core language support for garbage collection using e.g. the Boehm garbage collector. Smaller extensions include reference types, trailing function return types syntax, memory allocation and deallocation machinery that can be overridden, run time type information, and more.
The differences between C and C++, i.e. between C and the “C subset” of C++, are summarized in the C++11 standard's appendix C, entitled “Compatibility”, which is about 20 crammed pages, where the C1 section that pertains to C compatibility is about 10 pages.
It was appendix C also in C++98 and C++03, and it’s appendix C also in the fresh new C++14 standard.
As of C++11 appendix C of that standard lists the following incompatibilities between C and C++:
§C1.1 Lexical conventions
New keywords (§2.12)
The paragraph only refers to C++11 §2.12. The following list was generated from that table and a corresponding table in C99.
C99 C++11
_Bool
_Complex
_Imaginary
alignas
alignof
asm
auto auto
bool
break break
case case
catch
char char
char16_t
char32_t
class
const const
const_cast
constexpr
continue continue
decltype
default default
delete
do do
double double
dynamic_cast
else else
enum enum
explicit
export
extern extern
false
float float
for for
friend
goto goto
if if
inline inline
int int
long long
mutable
namespace
new
noexcept
nullptr
operator
private
protected
public
register register
reinterpret_cast
restrict
return return
short short
signed signed
sizeof sizeof
static static
static_assert
static_cast
struct struct
switch switch
template
this
thread_local
throw
true
try
typedef typedef
typeid
typename
union union
unsigned unsigned
using
virtual
void void
volatile volatile
wchar_t
while while
Type of character literal is changed from int
to char
(§2.14.3)
String literals made const
(§2.14.5)
§C1.2 Basic concepts
C++ does not have “tentative definitions” (§3.1).
A struct
is a scope in C ++ , not in C (§3.3).
A name of file scope that is explicitly declared const, and not explicitly declared extern
, has internal linkage, while in C it would have external linkage ($3.5).
main
cannot be called recursively and cannot have its address taken (§3.6).
C allows “compatible types” in several places, C++ does not (§3.9).
§C1.3 Standard conversions.
Converting void*
to a pointer-to-object type requires casting (§4.10).
Only pointers to non-const
and non-volatile objects may be implicitly converted to void*
(§4.10).
§C1.4 Expressions.
Implicit declaration of functions is not allowed (§5.2.2).
Types must be declared in declarations, not in expressions (§5.3.3, §5.4).
The result of a conditional expression, an assignment expression, or a comma expression may be an lvalue (§5.16, §5.17, §5.18).
§C1.5 Statements.
It is now invalid to jump past a declaration with explicit or implicit initializer (except across the entire block not entered) (§6.4.2, §6.6.4)
It is now invalid to return (explicitly or implicitly) from a function which is declared to return a value without actually returning a value (§6.6.3).
§C1.6 Declarations.
In C++, the static
or extern
specifiers can only be applied to the names of objects or functions. Using these specifiers with type declarations is illegal in C++ (§7.1.1).
A C++ typedef
name must be different from any class type name declared in the same scope
(except if the typedef
is a synonym of the class name with the same name) (§7.1.3).
const
objects must be initialized in C++ but can be left uninitialized in C (§7.1.6).
No implicit int
in C++ (§7.1.6).
The keyword auto
cannot be used as a storage class specifier (§7.1.6.4).
C++ objects of enumeration type can only be assigned values of the same enumeration type (§7.2).
In C++, the type of an enumerator is its enumeration (§7.2).
§C1.7 Declarators.
In C++, a function declared with an empty parameter list takes no arguments ($8.3.5).
In C++, types may not be defined in return or parameter types (§8.3.5, §5.3.3).
In C++, the syntax for function definition excludes the “old-style” C function (§8.4).
In C++, when initializing an array of characters with a string, the number of characters in the string (including the terminating '\0'
) must not exceed the number of elements in the array (§8.5.2).
§C1.8 Classes.
In C++, a class declaration introduces the class name into the scope where it is declared and hides any object, function, or other declaration of that name in an enclosing scope (§9.1, §7.1.3).
In C++, the name of a nested class is local to its enclosing class (§9.7).
In C++, a typedef
name may not be redeclared in a class definition after being used in that definition (§9.9).
§C1.9 Special member functions.
The implicitly-declared copy constructor and implicitly-declared copy assignment operator cannot make a copy of a volatile
lvalue (§12.8).
§C1.10 Preprocessing directives.
Whether __STDC__
is defined and if so, what its value is, are implementation-defined (§16.8).
To ease the regeneration of the comparative keyword table, and to build confidence in the one given, here’s the C++ program used to generate it:
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
#define ITEMS_OF( c ) c.begin(), c.end()
enum class Language { c, cpp };
auto compare( Language const a, Language const b )
-> int
{ return int( a ) - int( b ); }
struct Keyword
{
string word;
Language language;
friend
auto operator<( Keyword const& a, Keyword const& b )
-> bool
{
if( int const r = a.word.compare( b.word ) ) { return (r < 0); }
return (compare( a.language, b.language ) < 0);
}
};
void add_words_from(
string const& filename, Language const language, vector< Keyword >& words
)
{
ifstream f( filename );
string word;
while( getline( f, word ) )
{
words.push_back( Keyword{word, language} );
}
}
auto main() -> int
{
vector< Keyword > words;
add_words_from( "kwc.txt", Language::c, words );
add_words_from( "kwcpp.txt", Language::cpp, words );
sort( ITEMS_OF( words ) );
int const w = 20;
int previous_column = -1;
string previous_word = "";
cout << left;
for( Keyword const& kw : words )
{
int const column = (int) kw.language;
int const column_advance = column - (previous_column + 1);
if( column_advance < 0 || previous_word != kw.word )
{
cout << endl;
if( column > 0 ) { cout << setw( w*column ) << ""; }
}
else
{
cout << setw( w*column_advance ) << "";
}
cout << setw( w ) << kw.word;
previous_column = column; previous_word = kw.word;
}
cout << endl;
}