Class declaration
Member specification
class S {
int d1; // non-static data member
int a[10] = {1,2}; // non-static data member with initializer (C++11)
static const int d2 = 1; // static data member with initializer
virtual void f1(int) = 0; // pure virtual member function
std::string d3, *d4, f2(int); // two data members and a member function
enum {NORTH, SOUTH, EAST, WEST};
struct NestedS {
std::string s;
} d5, *d6;
typedef NestedS value_type, *pointer_type;
}
Function definitions
class M {
std::size_t C;
std::vector<int> data;
public:
M(std::size_t R, std::size_t C) : C(C), data(R*C) {} // constructor definition
int operator()(size_t r, size_t c) const { // member function definition
return data[r*C+c];
}
int& operator()(size_t r, size_t c) { // another member function definition
return data[r*C+c];
}
};
class S {
public:
S(); // public constructor
S(const S&); // public copy constructor
virtual ~S(); // public virtual destructor
private:
int* ptr; // private data member
};
class Base {
protected:
int d;
};
class Derived : public Base {
public:
using Base::d; // make Base's protected member d a public member of Derived
using Base::Base; // inherit all parent's constructors (C++11)
};
struct S {
template<typename T>
void f(T&& n);
template<class CharT>
struct NestedS {
std::basic_string<CharT> s;
};
};
template <typename T>
struct identity
{
using type = T;
};
local struct
int main()
{
std::vector<int> v{1,2,3};
struct Local {
bool operator()(int n, int m) {
return n > m;
}
};
std::sort(v.begin(), v.end(), Local()); // since C++11
for(int n: v) std::cout << n << ' ';
}
injected-class-name
int X;
struct X {
void f() {
X* p; // OK. X refers to the injected-class-name
::X* q; // Error: name lookup finds a variable name, which hides the struct name
}
};
struct A {
A();
A(int);
template<class T> A(T) {}
};
using A_alias = A;
A::A() {}
A_alias::A(int) {}
template A::A(double);
struct B : A {
using A_alias::A;
};
A::A a; // Error: A::A is considered to name a constructor, not a type
struct A::A a2; // OK, same as 'A a2;'
B::A b; // OK, same as 'A b;'
Non-static data members
struct A { int a; char b; };
struct B { const int b1; volatile char b2; };
// A and B's common initial sequence is A.a, A.b and B.b1, B.b2
struct C { int c; unsigned : 0; char b; };
// A and C's common initial sequence is A.a and C.c
struct D { int d; char b : 4; };
// A and D's common initial sequence is A.a and D.d
struct E { unsigned int e; char b; };
// A and E's common initial sequence is empty
Member initialization
struct S
{
int n;
std::string s;
S() : n(7) // direct-initializes n, default-initializes s
{ }
};
int x = 0;
struct S
{
int n = ++x;
S() { } // uses default member initializer
S(int arg) : n(arg) { } // uses member initializer
};
int main()
{
std::cout << x << '\n'; // prints 0
S s1;
std::cout << x << '\n'; // prints 1 (default initializer ran)
S s2(7);
std::cout << x << '\n'; // prints 1 (default initializer did not run)
}
struct X {
int a[] = {1,2,3}; // error
int b[3] = {1,2,3}; // OK
};
struct node {
node* p = new node; // error: use of implicit or defaulted node::node()
};
struct A
{
A() = default; // OK
A(int v) : v(v) { } // OK
const int& v = 42; // OK
};
A a1; // error: ill-formed binding of temporary to reference
A a2(1); // OK (default member initializer ignored because v appears in a constructor)
// however a2.v is a dangling reference
struct S
{
int m;
int n;
int x = m; // OK: implicit this-> allowed in default initializers (C++11)
S(int i) : m(i), n(m) // OK: implicit this-> allowed in member initializer lists
{
this->f(); // explicit member access expression
f(); // implicit this-> allowed in member function bodies
}
void f();
};
struct S
{
int m;
void f();
};
int S::*p = &S::m; // OK: use of m to make a pointer to member
void (S::*fp)() = &S::f; // OK: use of f to make a pointer to member
Non-static member functions
#include <iostream>
#include <string>
#include <utility>
#include <exception>
struct S {
int data;
// simple converting constructor (declaration)
S(int val);
// simple explicit constructor (declaration)
explicit S(std::string str);
// const member function (definition)
virtual int getData() const { return data; }
};
// definition of the constructor
S::S(int val) : data(val) {
std::cout << "ctor1 called, data = " << data << '\n';
}
// this constructor has a catch clause
S::S(std::string str) try : data(std::stoi(str)) {
std::cout << "ctor2 called, data = " << data << '\n';
} catch(const std::exception&) {
std::cout << "ctor2 failed, string was '" << str << "'\n";
throw; // ctor's catch clause should always rethrow
}
struct D : S {
int data2;
// constructor with a default argument
D(int v1, int v2 = 11) : S(v1), data2(v2) {}
// virtual member function
int getData() const override { return data*data2; }
// lvalue-only assignment operator
D& operator=(D other) & {
std::swap(other.data, data);
std::swap(other.data2, data2);
return *this;
}
};
int main()
{
D d1 = 1;
S s2("2");
try {
S s3("not a number");
} catch(const std::exception&) {}
std::cout << s2.getData() << '\n';
D d2(3, 4);
d2 = d1; // OK: assignment to lvalue
// D(5) = d1; // ERROR: no suitable overload of operator=
}
nested classes
struct enclose {
struct inner {
static int x;
void f(int i);
};
};
int enclose::inner::x = 1; // definition
void enclose::inner::f(int i) {} // definition
class enclose {
class nested1; // forward declaration
class nested2; // forward declaration
class nested1 {}; // definition of nested class
};
class enclose::nested2 { }; // definition of nested class
class enclose {
struct nested { // private member
void g() {}
};
public:
static nested f() { return nested{}; }
};
int main()
{
//enclose::nested n1 = enclose::f(); // error: 'nested' is private
enclose::f().g(); // OK: does not name 'nested'
auto n2 = enclose::f(); // OK: does not name 'nested'
n2.g();
}
Derived classes
Virtual base classes
struct B { int n; };
class X : public virtual B {};
class Y : virtual public B {};
class Z : public B {};
// every object of type AA has one X, one Y, one Z, and two B's:
// one that is the base of Z and one that is shared by X and Y
struct AA : X, Y, Z {
AA() {
X::n = 1; // modifies the virtual B subobject's member
Y::n = 2; // modifies the same virtual B subobject's member
Z::n = 3; // modifies the non-virtual B subobject's member
std::cout << X::n << Y::n << Z::n << '\n'; // prints 223
}
};
struct B {
int n;
B(int x) : n(x) {}
};
struct X : virtual B { X() : B(1) {} };
struct Y : virtual B { Y() : B(2) {} };
struct AA : X, Y { AA() : B(3), X(), Y() {} };
// the default constructor of AA calls the default constructors of B , X and Y
// but those constructors do not call the constructor of B because B is a virtual base
AA a; // a.n == 3
// the default constructor of X calls the constructor of B
X x; // x.n == 1
class A{
public:
A(){
cout<<"call A\n";
}
};
class B:virtual public A{
public:
B(){
cout<<"call B\n";
}
};
class C:virtual public A{
public:
C(){
cout<<"call C\n";
}
};
class D: public B,public C{
public:
D(){
cout<<"call D\n";
}
};
int main()
{
D b;
}
output
call A
call B
call C
call D
without virtual
output
call A
call B
call A
call C
call D
Using-declaration
#include <iostream>
struct B {
virtual void f(int) { std::cout << "B::f\n"; }
void g(char) { std::cout << "B::g\n"; }
void h(int) { std::cout << "B::h\n"; }
protected:
int m; // B::m is protected
typedef int value_type;
};
struct D : B {
using B::m; // D::m is public
using B::value_type; // D::value_type is public
using B::f;
void f(int) { std::cout << "D::f\n"; } // D::f(int) overrides B::f(int)
using B::g;
void g(int) { std::cout << "D::g\n"; } // both g(int) and g(char) are visible
// as members of D
using B::h;
void h(int) { std::cout << "D::h\n"; } // D::h(int) hides B::h(int)
};
int main()
{
D d;
B& b = d;
// b.m = 2; // error, B::m is protected
d.m = 1; // protected B::m is accessible as public D::m
b.f(1); // calls derived f()
d.f(1); // calls derived f()
d.g(1); // calls derived g(int)
d.g('a'); // calls base g(char)
b.h(1); // calls base h()
d.h(1); // calls derived h()
}
struct B1 { B1(int, ...) { } };
struct B2 { B2(double) { } };
int get();
struct D1 : B1 {
using B1::B1; // inherits B1(int, ...)
int x;
int y = get();
};
void test() {
D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
// then d.x is default-initialized (no initialization is performed),
// then d.y is initialized by calling get()
D1 e; // Error: D1 has no default constructor
}
struct D2 : B2 {
using B2::B2; // inherits B2(double)
B1 b;
};
D2 f(1.0); // error: B1 has no default constructor
struct A { A(int); };
struct B : A { using A::A; };
struct C1 : B { using B::B; };
struct C2 : B { using B::B; };
struct D1 : C1, C2 {
using C1::C1;
using C2::C2;
};
D1 d1(0); // ill-formed: constructor inherited from different B base subobjects
struct V1 : virtual B { using B::B; };
struct V2 : virtual B { using B::B; };
struct D2 : V1, V2 {
using V1::V1;
using V2::V2;
};
D2 d2(0); // OK: there is only one B subobject.
// This initializes the virtual B base class,
// which initializes the A base class
// then initializes the V1 and V2 base classes
// as if by a defaulted default constructor
virtual function specifier
struct A { virtual void f(); }; // A::f is virtual
struct B : A { void f(); }; // B::f overrides A::f in B
struct C : virtual B { void f(); }; // C::f overrides A::f in C
struct D : virtual B {}; // D does not introduce an overrider, B::f is final in D
struct E : C, D { // E does not introduce an overrider, C::f is final in E
using A::f; // not a function declaration, just makes A::f visible to lookup
};
int main() {
E e;
e.f(); // virtual call calls C::f, the final overrider in e
e.E::f(); // non-virtual call calls A::f, which is visible in E
}
class B {
virtual void do_f(); // private member
public:
void f() { do_f(); } // public interface
};
struct D : public B {
void do_f() override; // overrides B::do_f
};
int main()
{
D d;
B* bp = &d;
bp->f(); // internally calls D::do_f();
}
Virtual destructor
class Base {
public:
virtual ~Base() { /* releases Base's resources */ }
};
class Derived : public Base {
~Derived() { /* releases Derived's resources */ }
};
int main()
{
Base* b = new Derived;
delete b; // Makes a virtual function call to Base::~Base()
// since it is virtual, it calls Derived::~Derived() which can
// release resources of the derived class, and then calls
// Base::~Base() following the usual order of destruction
}
Covariant return types
class B {};
struct Base {
virtual void vf1();
virtual void vf2();
virtual void vf3();
virtual B* vf4();
virtual B* vf5();
};
class D : private B {
friend struct Derived; // in Derived, B is an accessible base of D
};
class A; // forward-declared class is an incomplete type
struct Derived : public Base {
void vf1(); // virtual, overrides Base::vf1()
void vf2(int); // non-virtual, hides Base::vf2()
// char vf3(); // Error: overrides Base::vf3, but has different
// and non-covariant return type
D* vf4(); // overrides Base::vf4() and has covariant return type
// A* vf5(); // Error: A is incomplete type
};
int main()
{
Derived d;
Base& br = d;
Derived& dr = d;
br.vf1(); // calls Derived::vf1()
br.vf2(); // calls Base::vf2()
// dr.vf2(); // Error: vf2(int) hides vf2()
B* p = br.vf4(); // calls Derived::vf4() and converts the result to B*
D* q = dr.vf4(); // calls Derived::vf4() and does not convert
// the result to B*
}