CPP的各类函数

ref

1 C++11之前
    1.1 非成员函数或自由函数
    1.2 成员函数
    1.3 可变参函数
    1.4 重载函数
    1.5 静态函数
    1.6 内联函数
    1.7 运算符重载函数
    1.8 只读成员函数
    1.9 友元函数
    1.10 虚成员函数
    1.11 特殊成员函数(构造、析构、拷贝、拷贝复制)
    1.12 函数模板、类模板、成员模板
2 C++11
    2.1 可变参模板函数
    2.2 返回值类型后置模板函数
    2.3 带override 说明符成员函数
    2.4 带final说明符成员函数
    2.5 增加的特殊成员函数(移动、移动赋值)
    2.6 default 成员函数(显式预置的函数定义)
    2.7 delete 成员函数(显式弃置的函数定义)
    2.8 delete 其他函数
    2.9 lambda 函数
3 C++14
    3.1 返回类型自动推导函数
    3.2 泛型lambda
4 C++17
    4.1 扩展 lambda
    4.2 向 lambda 传递 this 的拷贝
    4.3 异常声明作为函数类型的一部分
5 C++20
    5.1 consteval 函数(立即函数)
    5.2 简短的函数模板
    5.3 lambda 函数模板
    5.4 constexpr 虚成员函数
    5.5 协程
6 未来
    6.1 Contracts 合约

1 C++11之前

1.1 非成员函数或自由函数

int add(int a, int b)
{
   return a + b;
}

1.2 成员函数

它们是类/结构的一部分。这些也被称为方法(就像在大多数其他面向对象的编程语言中一样),尽管这个术语在C++标准中没有被使用。下面是一个例子:

class math
{
public:
   int add(int a, int b)
   {
      return a + b;
   }
};

1.3 可变参函数

#include <stdarg.h>
int sum(int count, ...);      //原型中使用省略号
int sum(int count, ...){      
    va_list ap;          
    va_start(ap, count);     
    int sum = 0;  
    for(int i = 0; i < count; i++)          
        sum += va_arg(ap, int);
    va_end(ap);             
    return sum;
}

1.4 重载函数

int add(int a, int b) {
    return a + b;
}
double add(double a, double b) {
    return a + b;
}

1.5 静态函数

static int add(int a, int b) {return a + b;}
struct math
{
   static int add(int a, int b) {return a + b;}
}

1.6 内联函数

inline int add(int a, int b) {return a + b;}
struct math
{
   inline int add(int a, int b);
}
int match::add(int a, int b) {return a + b;}

1.7 运算符重载函数

std::string operator+(std::string const & txt, int n)
{
    return txt + std::to_string(n); // channels your JavaScript energy
}

1.8 只读成员函数

class wrapper
{
public:
   wrapper(int a): value_(a) {}
   int get() const {return value_;}
private:
   int value_;
};

1.9 友元函数

class math
{
    int a,b;
public:
    math(int a,int b):a(a),b(b){}
   friend int add(math m);
};
int add(math m)
{
   return m.a + m.b;
}

1.10 虚成员函数

struct A
{
   virtual void f() { std::cout << "A::f()\n"; }
};
struct B : public A
{
   virtual void f() { std::cout << "B::f()\n"; }
};

1.11 特殊成员函数(构造、析构、拷贝、拷贝复制)

class wrapper
{
public:
   wrapper() : value_(0) {}
   wrapper(wrapper const & other) {value_ = other.value_; }
   wrapper& operator=(wrapper const & other) {if(this != &other) {value_ = other.value_;} }
   ~wrapper() {}
private:
   int value_;
};

1.12 函数模板、类模板、成员模板

template <typename T>
T add(T a, T b)
{
   return a + b;
}
template <typename T>
class math1
{
public:
   T add(T a, T b)
   {
      return a + b;
   }
};
class math2
{
public:
   template <typename T>
   T add(T a, T b)
   {
      return a + b;
   }
};

2 C++11

2.1 可变参模板函数

template <typename T>
T add(T a, T b)
{
    return a + b;
}
template <typename T, typename ...Ts>   // [1]
T add(T t, Ts ... rest)                 // [2]
{
    return t + add(rest...);            // [3]
}

2.2 返回值类型后置模板函数

auto add(int a, int b) -> int
{
   return a + b;
}
template<typename T, typename U>
auto add(T const & a, U const & b) -> decltype(a + b)
{
    return a + b;
}
constexpr 函数
template <typename T>
constexpr T add(T a, T b)
{
    return a + b;
}
int main()
{
    int arr[add(1,2)] = {1,2,3};    // [1]
    int a, b;
    std::cin >> a >> b;
    std::cout << add(a, b) << '\n';  // [2]
}

2.3 带override 说明符成员函数

struct A
{
   virtual void f(int) {}
   virtual void g() {}
};
struct B : public A
{
   void f(int) override {}  // OK
   void g(char) override {} // error, g() does not override anything
};

2.4 带final说明符成员函数

struct A
{
   virtual void f() {}
};
struct B : public A
{
   void f() override (final {}
};
struct C : public B
{
   void f() override {}   // error, f cannot be overridden anymore
};

2.5 增加的特殊成员函数(移动、移动赋值)

struct buffer
{
   buffer()                       // default constructor
       :data_(nullptr), size_(0) 
   {}
    
   explicit buffer(size_t size)   // constructor
       :data_(new char[size]), size_(size)
   {}
    
   ~buffer()                      // destructor
   {
       delete [] data_;
   }
   
   buffer(buffer const & other)   // copy constructor
      : data_(new char[other.size_])
      , size_(other.size_)
   {
      std::memcpy(data_, other.data_, size_);
   }
    
   buffer& operator=(buffer const & other) // copy assignment operator
   {
       if(this != &other)
       {
           delete [] data_;
           data_ = new char[other.size_];
           size_ = other.size_;
           std::memcpy(data_, other.data_, size_);
       }
       
       return *this;
   }
    
   buffer(buffer&& other)           // move constructor
       : data_(std::move(other.data_))
       , size_(other.size_)
   {
      other.data_ = nullptr;
      other.size_ = 0;
   }
    
   buffer& operator=(buffer&& other) // move assignment operator
   {
       if(this != &other)
       {
           delete [] data_;
           data_ = std::move(other.data_);
           size_ = other.size_;
           other.data_ = nullptr;
           other.size_ = 0;
       }
       
       return *this;
   }
    
private:
   char* data_;
   size_t size_;
};
int main()
{
  buffer b1;
  buffer b2(10);
  buffer b3 = b2;
  buffer b4 = std::move(b3);
}

2.6 default 成员函数(显式预置的函数定义)

struct foo
{
   foo(int) {}      // user-defined constructor
   foo() = default; // compiler generated default constructor
};

2.7 delete 成员函数(显式弃置的函数定义)

struct noncopyable
{
  noncopyable() = default;
  noncopyable(noncopyable const &) = delete;
  noncopyable& operator=(noncopyable const &) = delete;
};

2.8 delete 其他函数

template <typename T>
T add(T a, T b)
{
    return a + b;
}
template <>
int add<int>(int a, int b) = delete;
int main()
{
    add(1, 2); // error, this specialization is deleted
}

2.9 lambda 函数

int main()
{
    auto add = [](int a, int b) { return a + b; };
    add(1, 2);
}

3 C++14

3.1 返回类型自动推导函数

auto add(int a, int b)
{
   return a + b;
}
template <typename T, typename U>
auto add(T a, U b)
{
   return a + b;
}

3.2 泛型lambda

int main()
{
    using namespace std::string_literals;
    
    auto add = [](auto a, auto b) {return a + b;};
    
    add(1, 2);
    add(1.0, 2.0);
    add("1"s, "2"s);
}

4 C++17

4.1 扩展 lambda

constexpr lambda,自从 C++17 起,lambda表达式会尽可能的隐式声明 constexpr。

auto squared = [](auto val) { // 自 从C++17起 隐 式constexpr
    return val*val;
};
std::array<int, squared(5)> a; // 自 从C++17起OK => std::array<int, 25>

4.2向 lambda 传递 this 的拷贝

class C {
private:
    std::string name;
public:
    void foo() {
        auto l1 = [*this] { std::cout << name << '\n'; };
    }
};

4.3 异常声明作为函数类型的一部分

这里,派生类中的成员函数 foo() 和基类中的 foo() 类型不同所以不能重载。这段代码不能通过编译,即使 没有 override 修饰符代码也不能编译,因为我们不能用更宽松的异常声明重载。

class Base {
public:
    virtual void foo() noexcept;
};
class Derived : public Base {
public:
    void foo() override; // ERROR: 不 能 重 载
    //...
};

5 C++20

5.1 consteval 函数(立即函数)

consteval int add(int const a, int const b)
{
   return a + b;
} 
int main()
{
   constexpr int s1 = add(1, 2);   // OK, compile-time evaluation
   int a = 12, b = 66;
   const int s2 = add(a, b);       // error
    
   using fptr = int(int, int);
   fptr* padd = add;               // error
}

5.2 简短的函数模板

auto add(auto a, auto b)
{
   return a + b;
}

5.3 lambda 函数模板

auto add = [](auto a, auto b) {return a + b;};

5.4 constexpr 虚成员函数

struct magic
{
    constexpr virtual int def() const { return 0; }
};
struct programming_magic : public magic
{
    constexpr int def() const (override { return 42; }
};
constexpr int initval(magic const & m)
{
    return m.def() + 1;
}
int main()
{
   constexpr programming_magic pm;
   int arr[initval(pm)] = {0};
}

5.5 协程

协程,这个是C++20标准的主要特征之一。coroutine是一个具有暂停和恢复能力的函数。不幸的是,C++20只定义了一个执行程序的框架,但并没有定义任何满足这种要求的程序类型。这意味着,我们需要自己编写或者依靠第三方库来实现。这样一个库就是cppcoro库。在C++20中,有三个新的关键字,用于coroutine:co_await,co_return,和co_yield。如果一个函数使用了这三个中的一个,它就会成为一个循环程序。

co_await操作符,用于暂停执行,直到重新开始。

co_return关键字,完成执行并可选返回一个值

co_yield关键字用于暂停执行并返回一个值

#include <cppcoro/generator.hpp>
cppcoro::generator<std::string> produce_items()
{
  while (true)
  {
     auto v = rand();
     using namespace std::string_literals;
     auto i = "item "s + std::to_string(v);
     print_time();
     std::cout << "produced " << i << '\n';
     co_yield i;
  }
}
#include <cppcoro/task.hpp>
cppcoro::task<> consume_items(int const n)
{
  int i = 1;
  for(auto const& s : produce_items())
  {
     print_time();
     std::cout << "consumed " << s << '\n';
     if (++i > n) break;
  }
  co_return;
}

6 未来

6.1 Contracts 合约

前提条件(Preconditions):你对输入值的期望/要求是什么?

后置条件(Postconditions):对于输出值,你应该给出什么保证?

不变量(Invariants):你的函数的调用者/使用者期望什么不会改变?

目的(Purpose):你的函数是否有一个明确的目的?

名称(Name):该函数的名称是否反映了它的目的?

参数(Parameters):调用者/用户能轻易混淆它们的含义吗?

前提条件检查:

宽合约函数执行前提条件检查,即检查输入参数值(或程序状态)的有效性。

窄合约函数不执行前提条件检查,即调用者必须确保输入参数(和程序状态)是有效的。

本页共502段,19645个字符,21857 Byte(字节)