学不会的 吸佳佳

笔记 / 2020-11-02

C++ 三大特性

封装

客观的事物封装成抽象的类(将数据和方法打包在一起,加权限的区分)

多态

简单概括为一个接口多种方法(面向未来编程)

继承

表达的是类与类之间的关系,使得对象可以继承另一对象的特征和能力。
目的: 减少代码冗余

作用域

#include <iostream>

using namespace std;

int a =10;
void test01(){
    int a =20;
    // 就近原则 优先选择局部变量
    cout <<"局部变量:"<< a <<endl;
    // 作用域 运算符
    cout << "全局变量:"<<::a<<endl;
}

int main()
{
    test01();
    return 0;
} 

命名空间

  • 为了解决命名冲突
  • 可以重复嵌套
  • 可以声明实现分离
  • 可在命名空间外部定义
  • 通过using 引入

定义

namespace NameSpaceA {
    int a  =10;
    void sayHello(){
        std::cout<<"A: Hello World!"<<std::endl;
    }
}

namespace NameSpaceB {
    int a =20;
    void sayHello(){
        std::cout<<"B: Hello World!"<<std::endl;
    }
}


// 嵌套的命名空间
namespace OuterSpace {
    int a =10;
    namespace InnerSpace {
        int a =20;
    }
}

// 命名空间是开放的 可以随时加入
// 引入重载
namespace NameSpaceA {
void sayHi(){
    std::cout <<"Hi World!"<<std::endl;
}
void func(bool flag){std::cout<<flag<<std::endl;}
void func(int a){std::cout<<a<<std::endl;}
void func(int a,int b){std::cout<<a<<","<<b<<std::endl;}
}


// 声明实现分离
namespace TestSpace {
    void hello();
    void test();
}

// 命名空间外部定义
void TestSpace::test(){
    std::cout <<"test"<<std::endl;
}

// 声明分离
namespace TestSpace {
    void hello(){
        std::cout <<"hello" <<std::endl;
    }
}

// 命名空间别名
namespace VeryLongNameHHHHHHHH {
    bool flag =false;
}

使用

可以使用 using 引入命名空间(引入后可直接使用)

没有引用的要加 作用域运算符 来指定

#include <iostream>
#include "nameSpace.hpp"
using namespace std;
using namespace NameSpaceB;

int main()
{
    NameSpaceA::sayHello(); // 指定使用
    sayHello(); // 引入后直接使用
    
    cout <<"外部空间:"<<OuterSpace::a<<endl;
    cout <<"内部空间:"<<OuterSpace::InnerSpace::a<<endl;
    NameSpaceA::sayHi();
    
    // 命名空间别名
    namespace shortSpace = VeryLongNameHHHHHHHH;
    cout.setf(ios::boolalpha);
    cout <<shortSpace::flag<<endl;
        
    // 引入部分
    using NameSpaceA::func;

    func(1);
    func(1,2);
    func(false);

    return 0;
}

无名命名空间

namespace{
    
}

意味仅本文件内使用

结构体

struct Student{
    string name;
    int id;
};

C++ 中结构体 使用可以不加 struct关键字

// struct Student s1 = {"jack",1}; // c-style
Student s1={"jack",1};

成员函数

struct Student{
private:
    string name;
    int id;
public:
    string getName() const{
        return this->name;
    }
    void setName(const string name){
        this->name=name;
    }

    int getId()const{
        return this->id;
    }
    void setId(const int id){
        this->id=id;
    }
    Student(string name,int id):name(name),id(id){}
};

在C++中结构体内可以定义函数,和变量。

bool

C++ 中引入了布尔类型 bool

bool flag = true;

三目运算符

C语言三目运算符表达式返回值为数据值,为右值,不能赋值.

int a =10;
int b =20;
printf("ret:%d\n",a>b?a:b);

C++三目运算符返回右值引用,可以被赋值。

int a=10,b=20;

a>b?a:b = 100;

cout <<"a:"<<a<<endl
    <<"b:"<<b<<endl;

const

C语言中 const表示只读变量,默认是外部链接(其他源文件可以使用)

func.c

const int num =100;

main.c

extern const int num;

printf("%d",num);

C++ const修饰的全局变量,默认是内链接(只在当前文件使用)

c++ 中基础类型 不会开辟空间, 会放到符号表中

因此下面的修改是无效的

const int data  =10;

int* const ptr = (int*)&data;
*ptr  = 100;
cout <<"data:"<<data<<endl;

符号表

int _a = 10;
const int _b =_a; // 系统会开辟空间
int* const _ptr =(int*)&_b;
*_ptr =100;

cout <<"_a:"<<_a<<endl;
cout <<"_b:"<<_b<<endl;

但是当我们把代码修改成这样,会发现值被修改了。

因为当我们创建变量_b 时系统并没有将其放入到符号表中。

尽量使用const替换define

引用

已知变量的别名

int a =10;
int& r1 = a; // 这里并不是取地址 r1 是 a 的引用(别名)
// int* p =&a; // 取地址

能用引用,不用指针!

// 引用
int num =1;
int& r1 =num;
cout <<"num:"<<&num<<endl;
cout <<"r1:"<<&r1<<endl;
num:0x61fe48
r1:0x61fe48

地址是相同的!

  • 引用必须初始化
  • 引用一旦初始化就不能再次修改别名

引用数组

// 引用数组

int arr[5]={0,1,2,3,4};

// 注意 加()区分 全部引用 和 局部引用
int(& r2)[5] = arr;
r2[0]=1;
vector<int> vc(arr,arr+5);
for_each(vc.begin(),vc.end(),[&](int t){
    cout <<t<<
        " ";
});

1 1 2 3 4

当然为了解决上面问题我们也可用typedef


// typedef 类型起别名

typedef int TYPE_ARR[5];

TYPE_ARR& rArr =arr;
cout <<rArr[0]<<endl;