C++语言基础快查

C++兼容C语言,所以基础部分可以 参考C语言基础快查。


C++数据类型

C++比C的整型多了个布尔类型 布尔型 bool, bool类型变量占用内存1字节


C++ 中的类型限定符

限定符 说明
const                     const 类型的对象在程序执行期间不能被修改。
volatile           修饰符 volatile 告诉编译器不需要优化volatile声明的变量,让程序可以直接从内存中读取变量。对于一般的变量编译器会对变量进行优化,将内存中的变量值放在寄存器中以加快读写效率。
restrict           由 restrict 修饰的指针是唯一一种访问它所指向的对象的方式。只有 C99 增加了新的类型限定符 restrict。

存储类

mutable

mutable 能用来修饰类的数据成员,被 mutable 修饰的数据成员,可以在 const 成员函数中修改。比如const意思是“这个函数不修改对象内部状态”,mutable意思是“这个成员变量不算对象内部状态”,mutable告诉编译器修改它并不影响const语义,所以就不需要禁止const函数修改它。

thread_local

thread_local 声明的变量仅可在它在其上创建的线程上访问。 变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。

  • thread_local 说明符可以与 static 或 extern 合并。
  • thread_local 仅应用于数据声明和定义,thread_local 不能用于函数声明或定义。
// 命名空间下的全局变量
thread_local int x;  
class X
{
    // 类的static成员变量
    static thread_local std::string s;
};
static thread_local std::string X::s;  // X::s 是需要定义的

void foo()
{
    // 本地变量
    thread_local std::vector v;  
}

C++ 引用

C++比C多了引用类型,其实引用就是给变量的一个别名

  • 没有空引用,引用必须连接到一块合法的内存。
  • 一旦引用被初始化为一个对象,就不能被指向到另一个对象。
  • 引用必须在创建时被初始化。
int a = 1;
int&  ref = a;

那么ref就是aa也是ref


C++ 函数

C++ 函数在C的函数又增加了为参数指定默认值等特性。

参数默认值

定义函数时,可以为参数列表中后边的每一个参数指定默认值。当调用函数时,实参的值留空,形参就使用这个默认值。

int sum(int a, int b= 1);
int sum(int a = 0, int b = 1);

int sum(int a =0, int b); 这样不行

引用作为参数

引用作为参数,函数内部实际上使用的是实参,不会引起形参的拷贝。

void swap(int& x, int& y)
{
   int temp;
   temp = x; /* 保存地址 x 的值 */
   x = y;    /* 把 y 赋值给 x */
   y = temp; /* 把 x 赋值给 y  */
 
   return;
}

引用作为返回值

static int sum = 0;
int& swap(int& x, int& y)
{
   sum = x + y;
   return sum;
}

C++ 类 & 对象

面向对象的基本特征:封装、继承和多态。

C++ 类定义

class People
{
   public:
      std::string name; 
      double age; 
};

定义 C++ 对象

People people;

数据成员访问

people.name = "XiaoMing";

类成员函数

类成员函数声明:

class People
{
   public:
      std::string name; 
      double age; 
      void run(void);
};

类成员函数定义:直接在类里面定义

class People
{
   public:
      std::string name; 
      double age; 
      void run(void){
          std::out<<"run"<

类成员函数定义:在类外定义
类外定义需要使用范围解析运算符::, ::的前面是类名,::后面是函数名

void People::run(void){
    std::out<<"run"<

类成员函数调用:

People people;
people.run();

类访问修饰符

在修饰数据成员或者成员函数时:

修饰符 说明
public 公有成员:类内外均可访问
private 私有成员:只有本类或者友元类/函数可以访问
protected 保护成员:本类、友元类/函数、派生类是可访问的

class内默认访问权限是private,struct默认访问权限是public。

构造函数

创建新对象时被自动调用执行,函数名与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void,可以带参数。
如果一个类没有定义任何构造函数,编译器会创建合成的默认构造函数
构造函数作用:为某些成员变量设置初始值。

class People
{
   public:
      People();//<--构造函数
      std::string name; 
      double age; 
      void run(void);
};

People people;

带参数的构造函数。

class People
{
   public:
      People(std::string name);//<--带参数的构造函数
      std::string name; 
      double age; 
      void run(void);
};

People people("XiaoMing");

如果想在自定义其他构造函数的同时保留默认的构造函数。在类定义添加默认构造函数声明 = default 即可。

People() = default;

初始化列表

class People
{
   public:
      People(std::string name):name(name);//<--初始化列表
      std::string name; 
      double age; 
      void run(void);
};

People people("XiaoMing");

析构函数

对象被销毁时自动调用。名称与类的名称是完全相同的,需要前面加了个波浪号(~)作为前缀,不返回任何值,也不带任何参数。
主要用来用来在对象销毁前释放对象申请的资源。

class People
{
   public:
      People();//<--构造函数
      ~People();
      std::string name; 
      double age; 
      void run(void);
};

People people;

拷贝构造函数

创建对象可以使用一个存在的对象初始化新对象。

  • 如果类中没有定义拷贝构造函数,编译器会自行定义一个。
  • 如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数。
class People
{
   public:
      People();//<--构造函数
      People(const  People& aPeople){
      }
      ~People();
      std::string name; 
      double age; 
      void run(void);
};

People people;
People other = People(people);

友元函数

类的友元函数是定义在类外部,声明在类的内部,表示这个外部函数可以访问类的保护和私有成员。
友元函数不是成员函数。

class People
{
   public:
      People();
      friend void sayHello( People &people );
      ~People();
      std::string name; 
      double age; 
      void run(void);
};

this 指针

对象使用 this 指针来访问自己的地址,自有成员函数才有 this 指针。

class People
{
   public:
      People();
      ~People();
      std::string name; 
      double age; 
      void setName(std::string name){
          this->name = name;
      }
};

指向类的指针

指向类的指针和指向结构体的指针一致。可以使用成员访问运算符 ->来访问成员,或者解引用*的方式引用指针。

People tom = People();
People *ptr = &tom;
std::cout>>ptr->name>>std::endl;
std::cout>>(*ptr).name>>std::endl;

类的静态成员

static 把类成员定义为静态成员。

  • 包括静态成员变量和静态成员函数。
  • 静态成员变量只存在一份,普通成员和静态成员函数都可访问静态成员变量。
  • 静态成员函数可以访问静态成员变量,不能直接访问类普通成员,没有this指针。
// People.h
class People
{
   public:
      People();
      ~People();
      std::string name; 
      double age; 
      static std::string className;
      static std::string &getClassName(){
          return className;
      }
};

静态成员变量的初始化在类外面进行

//People.cpp 
std::string People::className = "People";

外部使用位运算符::访问

std::cout<

继承

使用已有的类定义新的类,新的类含有原来类的成员的同时,可以创建新的新的成员。
已有的类称为基类,新建的类称为派生类。

继承的格式

class 派生类: 访问控制符 基类

class People
{
   public:
      People();
      ~People();
      std::string name; 
      double age; 
      void setName(std::string name){
          this->name = name;
      }
};

class Chinese: public People{
 public:
      std::string id_number;
}

继承访问控制符

继承不写访问控制符:

  • class 的默认继承方式是: private
  • struct 的默认继承方式是:public

派生类继承了所有的基类方法,下列情况除外:

  • 基类的构造函数、析构函数和拷贝构造函数。
  • 基类的重载运算符。
  • 基类的友元函数。

public继承:(最大public)
public成员是pulic的,protected成员是protected的,private成员无法继承。

protected继承:(最大protected)
public成员是protected的,protected成员是protected的,private成
员无法继承。

private继承:(最大private)
public成员是private的,protected成员是private的,private成员无法继承。

多继承

多继承格式:
class 派生类: 访问控制符 基类1, 访问控制符 基类2, 访问控制符 基类3, ...

多个基类中含有同名函数,会产生二义性,在访问时可以加上域控制符:

#include 
using namespace std;

class classA{
public:
    void func (int aInt){
        cout<<"classA::func"<

或者在派生类中通过using声明,把基类中的同名函数都引入到一个公共域中,这样重载解析规则就可以正常使用。

class classC: public classA, public classB{
public:
    using classA::func;  //!!!!
    using classB::func;
};

int main(int argc, const char * argv[]) {
    classC obj = classC();
    obj.func('a');  // 这里就可以了
    return 0;
}

但是如果基类包含一模一样函数使用using是无法编译通过的。

多态

通过继承关系为不同的类的实体提供统一的接口。使用接口调用时,会根据调用函数的对象的类型来执行不同的函数。

C++通过关键字virtual实现继承的多态。

虚函数 :在基类中使用 virtual 声明的函数。派生类中重新定义基类中定义的虚函数时,会告诉编译器不要静态链接到该函数

class People{
public:
    virtual void sayHello(){
        cout<<"I am people"<sayHello();
    
    ptr = &teacher;
    ptr->sayHello();
    
    return 0;
}

运行结果如下:

I am Studenmt
I am Teacher

如果基类的sayHello不使用virtual修饰,那么main函数中的指针ptr时静态绑定的,指向派生类对象的基类的方法

比如把sayHello的virtual去掉:

class People{
public:
    void sayHello(){
        cout<<"I am people"<

结果如下,都是运行的基类的方法:

I am people
I am people

如果在基类中定义虚函数,但不想在基类中实现该函数,就可以使用纯虚函数,如果。

virtual void sayHello() = 0;

含有纯虚函数的类叫做抽象类,如果它的派生类不实现基类中的纯虚函数,那么这个派生类也是抽象类抽象类不能定义对象


重载、重写(覆盖)、隐藏

重载 overload

同一作用域中,同名函数的形式参数(参数个数、类型或者顺序)不同时,构成函数重载。

  • 函数返回值类型与构成重载无任何关系
  • 类的静态成员函数与普通成员函数可以形成重载。
  • 函数重载发生在同一作用域,如类成员函数之间的重载、全局函数之间的重载。

你可能感兴趣的:(C++语言基础快查)