C/C++ 专题知识《简书与写作》知识图谱

C++ 常用小点

2021-03-31  本文已影响0人  zcwfeng

1. C++ 自定义String

c语言常量不能修改,但是可以通过指针修改
const int num = 100;
int *pnum = #
*pnum = 10000;

但是在C++中 const 是不能修改的指针也不行

自定义String
header



#ifndef TEMPC_MYSTRING_H
#define TEMPC_MYSTRING_H

#include <iostream>
using namespace std;
class MyString {

public:
    MyString(int len = 0);
    MyString(const char *p);
    MyString(const MyString &s);
    virtual ~MyString();
    friend istream &operator>>(istream&in,MyString &s);
    friend ostream &operator<<(ostream&out,MyString &s);
public: // 重载=
    MyString &operator=(const char *p);
    MyString &operator=(const MyString &s);
    char &operator[](int index);
public://重载== !=
    bool operator==(const char *p) const;
    bool operator==(const MyString &s) const;
    bool operator!=(const char *p) const;
    bool operator!=(const MyString &s) const;
public: //重载<,>
    bool operator<(const char *p);
    bool operator<(const MyString &s);
    bool operator>(const char *p);
    bool operator>(const MyString &s);
public:// 类的指针
    char *s_str(){
        return m_p;
    }
    const char *c_str2(){
        return m_p;
    }
    int length(){
        return m_len;
    }
private:
    int m_len;
    char *m_p;

};

#endif //TEMPC_MYSTRING_H

cpp

//
// Created by 张传伟 on 2020/8/7.
//

#include "MyString.h"
istream &operator>>(istream &in, MyString &s) {
    in >> s.m_p;
    return in;
}

ostream &operator<<(ostream&out, MyString &s) {
    out << s.m_p;
    return out;
}
MyString::MyString(int len) {
    if(len == 0){
        m_len = 0;
        m_p = new char[m_len + 1];
        strcpy(m_p,"");
    }else{
        m_len = len;
        m_p = new char[m_len + 1];
        memset(m_p,0,m_len);
    }

}



MyString::MyString(const char *p) {
    if(p==NULL){
        m_len = 0;
        m_p = new char[m_len + 1];
        strcpy(m_p,"");
    } else {
        m_len = strlen(p);
        m_p = new char[m_len + 1];
        strcpy(m_p,p);
    }
}

MyString::~MyString() {
    if(m_p != NULL){
        delete[] m_p;
        m_p = NULL;
        m_len = 0;
    }
}

MyString::MyString(const MyString &s) {
    m_len = s.m_len;
    m_p= new char[m_len +1];
    strcpy(m_p,s.m_p);
}

MyString &MyString::operator=(const char *p) {
    // 旧的内存释放
    if(m_p!=NULL){
        delete(m_p);
        m_len = 0;
    }
    // 根据p 分配内存
    if(p==NULL){
        m_len = 0;
        m_p = new char[m_len + 1];
        strcpy(m_p,"");
    } else{
        m_len = strlen(p);
        m_p = new char[m_len + 1];
        strcpy(m_p,p);
    }
    return *this;
}

MyString &MyString::operator=(const MyString &s) {
    // 旧的内存释放
    if(m_p!=NULL){
        delete(m_p);
        m_len = 0;
    }
    m_len = s.m_len;
    m_p = new char[m_len + 1];
    strcpy(m_p,s.m_p);
    return *this;
}

char &MyString::operator[](int index) {
    return m_p[index];
}

bool MyString::operator==(const char *p) const {
    return false;
}

bool MyString::operator==(const MyString &s) const {
    if(m_len != s.m_len){
        return false;
    }
    return !strcmp(m_p,s.m_p);
}

bool MyString::operator!=(const char *p) const {
    if(p == NULL) {
        if(m_len == 0){
            return true;
        } else {
            return false;
        }
    }else {
        if(m_len == strlen(p)){
            return !strcmp(m_p,p);
        } else {
            return false;
        }
    }
}

bool MyString::operator!=(const MyString &s) const {
    return !(*this == s);
}

bool MyString::operator<(const char *p) {
    return strcmp(this->m_p,p);

}

bool MyString::operator<(const MyString &s) {
    return strcmp(this->m_p,s.m_p);
}

bool MyString::operator>(const char *p) {
    return strcmp(p,this->m_p);
}

bool MyString::operator>(const MyString &s) {
    return strcmp(s.m_p,m_p);
}


Test

int main() {
    MyString s1;
    MyString s2("s2");
    MyString s2_2 = "";
    MyString s3 = s2;
    MyString s4 = "4444444";

    s4 = s2;
    s4 = "s2222";
    s4[1] = '4';
    printf("%c\n",s4[1]);
    cout<< s4 << endl;
    return 0;
}

2. C++ 基础 const #define

const 总结

const & #define 相同和不同

尝试几种 define

-> 定义在外面的

#define ABC 10

void fun1() {
    #define ABC1  30
        const int ABC2 = 40;
-> 有卸载的
    #undef ABC1
}

void fun1() {
-> 定义在里面的
    #define ABC1  30
    const int ABC2 = 40;
}

测试代码:

#include <iostream>
#include "../jni.h"

using namespace std;

struct Teacher {
    char name[20];
    int age;
};

int operatorT1(const Teacher *pT) {// 常量指针表示一种输入参数,能够使用不能够修改
//    pT->age = 23;
    cout << pT->age << endl;
    pT = NULL;
}

int operatorT1(Teacher *const pT) {// 输出
    pT->age = 23;// 输出参数
    cout << pT->age << endl;
//    pT = NULL;
}

/**
 * 1 const 可以有效提高代码的可读性,减少bug
 * 2. 清楚区分输入还是输出参数
 *
 *   const  & #define 相同和不同
 *  #define 是预处理阶段简单文本替换
 *  const 编译器处理,提供类型检查和作用与检查
 * @return
 */

#define ABC 10

void fun1() {
    #define ABC1  30
        const int ABC2 = 40;
    #undef ABC1
}

void fun2(){
    cout << ABC1 << endl;
//    cout << ABC2 << endl;
}

int main() {
    int a = 1;
    int b = 10;
    const int *c;//常量指针,修饰指针指向的变量,代表指针指向的内存空间,不能修改
    c = &a;
    cout << *c << endl;

    c = &b;
//    *c = 20; 常量指针不允许修改指针所指向的内存控件
    cout << c << endl;
    cout << &a << endl;
    cout << *c << endl;
    cout << &c << endl;
    cout << "------------------" << endl;

    int a1 = 100;
    int *const e = &a1;//指针常量,修饰的是指针本身,指向不可以改变
//    e = &b;
    cout << *e << endl;
    *e = 20;
    cout << *e << endl;
    cout << "------------------" << endl;

    const int *const d = &a1;//常量指针常量

    return 0;

}

3. C++ 类构造函数 new malloc calloc delete 和 C++ 四驱模型



全局区
方法区

malloc/clloc 分配到堆上

/*

/*

// new delete /new[] delete[]
// 对象的动态创建和释放
// 在栈上创建对象 和释放对象 与 在堆上创建对象和释放对象 的区别
// 栈
// 1. 在栈上创建的对象,一经创建,对象的大小是无法改变的
// 2. 在栈上的对象 系统自动创建和销毁
// 堆
// 1. 堆上申请的内存空间 是可以动态调整的
// 2. 堆上的申请的空间,必须自己申请与释放

// malloc/calloc free C语言的 是函数
// new delete C++的语法 new delete 它们是属于运算符 不是函数

#include <iostream>

using namespace std;

class Test {
public:

    int getA() const {
        return a;
    }

    int getB() const {
        return b;
    }
    Test() {
        a = 10;
        b = 0;
        p = (char *)malloc(100);
        strcpy(p,"abcdefghijk");
        cout << "构造函数" << endl;
    }

    Test(int ma){
        a = ma;
        b = 0;
        cout << "有一个参数构造函数a:" << a << ",b:" << b << endl;
    }

    Test(int ma,int mb){
        a = ma;
        b = mb;
        cout << "有2个参数构造函数a:" << a << ",b:" << b << endl;
    }

    // 拷贝构造函数
//    Test(const Test& obj){
//        a = obj.a;
//        b = obj.b;
//        cout << "拷贝数构造函数a:" << a << ",b:" << b << endl;
//    }

    Test(const char *arg){
        a = 20;
        b = 20;
        p = (char *)malloc(100);
        strcpy(p,arg);
        cout << "浅拷贝构造函数" << endl;
    }


    // 拷贝构造函数,深浅拷贝
    Test(const Test& obj){
        a = obj.a;
        b = obj.b;
        p = (char *)malloc(100);
        strcpy(p,obj.p);
        cout << "深拷贝数构造函数a:" << a << ",b:" << b << endl;
    }

    void init(int ma,int mb){
        a = ma;
        b = mb;
    }

    ~Test() {
        if(p != NULL) {
            free(p);
        }
        cout << "析构函数a:" << a << ",b:" << b <<endl;
    }
    //成员函数
    void print(){
        cout << "a:" << a << ",b:" << b << endl;
    }


private:
    int a;
    int b;
    char *p;
};

void copyTest(Test t){
    cout << "对象参数传递a:" << t.getA() << ",b:" << t.getB() << endl;
}

void objtest1(){
    Test t1;
    t1.print();
}

void objtest2(){
    // 自动调用 括号法
    Test t1(2,3);
    Test t2(2);
    // 自动调用 = 法
    Test t3 = (4,5);
    Test t4 = 9;
    // 手动调用
    Test t5 = Test(1,5);

    t1 = t5;// 这个是赋值操作t5 copy 给 t1;
    // 调用拷贝构造函数
    Test t6 = t5;
    Test t7(t5);

}

void objtest3(){
    Test t1;
    t1.init(2,3);
    Test arr[3];
    arr[0].init(1,3);
    arr[1].init(1,3);
    arr[3].init(1,3);
}

void objtest4() {
    Test t1(10,20);
    Test t2 = t1;
    t2.print();
    printf("objtest4\n");

    copyTest(t2);

}

Test getTest(){
    Test t(100,200);
    return t;
}

void objtest5() {
    Test t = getTest();// 匿名对象转换成有名的
    t.print();
}

void objtest6() {
    Test t (123,456);
    t = getTest();// 出事话过了t,在这样就相当于赋值
    t.print();
}

int main() {
//    objtest1();
//    objtest2();
//    objtest3();
//    objtest4();
//    objtest5();
//    printf("objtest5================\n");

    objtest6();


    return 0;
}

new delete

c 和 C++分配内存

-> c
     int *p = (int *)malloc(sizeof(int));//堆分配内存
    *p = 10;
    free(p);
    p=NULL;
    
    -> C++
      int *p1 = new int;// 堆申请内存分配基础类型
    *p1 = 20;
    
    delete p1;

  -> c 数组init
  int *array = (int *)malloc(sizeof(int) * 10);//int array[10] C
    array[0] = 20;
    free(array);
    -> C++ 数组
    int *array1 = new int[10];//int array[10] C++
    array1[2] = 30;
    delete[] array1;//数组的释放方式


------------------

class Test1{
public:
    Test1(int i) {
        cout << "构造函数" << endl;
    }

    void print(){
        cout << m_a << endl;
    }

    virtual ~Test1() {
        cout << "析构函数" << endl;
    }
private:
    int m_a;
};
-> C
Test1 *pt1 = (Test1 *)malloc(sizeof(Test1));
    pt1->print();
    free(pt1);
-> C++ 会调用构造和析构
    Test1 *pt2 = new Test1(10);
    pt2->print();
    delete pt2;

4. C++ 继承

结构体继承,默认 public
class继承,默认private

class 继承关系:

内部集成public,private,protected差不多
外部只有public集成才可以访问public修饰成员

家族成员使用:继承protected
外部使用:集成用public

单个继承访问父类成员

class A {
public:
    int a = 1;
    int b = 2;

    void print() {
        cout << "A print" << "a:" << a << "b:" << b << endl;
    }
};


class B: public A {
public:
    int a = 3;
    int b = 4;

    void print() {
        cout << "B print" << "a:" << a << "b:" << b << endl;
    }
};

-> b::A.xxxx
   B b;
    b.print();
    b.A::print();

c++ 多继承

5. c++ 多态&virtual

解决多继承的二义性:

class B_ {
public:
    int b;
};

class Base1_ :virtual public B_ {

};

class Base2_ : virtual public B_ {

};

class C : public Base1_, public Base2_ {

};

int main() {
    C c;
    c.b = 100;// 存在继承的二义性,解决方案是使用virtual 虚继承
    c.Base1_::b = 20;
    c.Base2_::b = 30;
    return 0;
}

抽象类,重载和重写
//重写 重载 重定义
//重写 发生在两个类 虚函数重写 多态
//1 虚函数 多态
//2 非虚函数 重定义
//重载
//必须是发生在同一个类之间

//抽象类,无法实例化
class Shape {
public:
    virtual void area() = 0;// 关键字 = 0;纯虚函数
    // 重载
    virtual void func(){

    }
    // 重写
    void print(){
        cout << "shape" <<endl;
    }
};
class Circle:public Shape{
private:
    int r;
public:
    Circle(int r=0):r(r){}
    virtual void area(){
        cout << "circle area:" << 3.14 * r * r << endl;
    }
    virtual void func(){

    }
    void printf(){
        cout << "Circle" <<endl;
    }
};
class Tri:public Shape{
public:
    Tri(int a,int h):a(a),h(h){

    }
    virtual void area(){
        cout << "tri area:" << a * h /2 << endl;
    }

private:
    int a;
    int h;
};

int main() {
    Shape * shape = nullptr;
    Circle c(10);
    Tri tri(3,6);
    shape = &c;
    shape->area();
    shape = &tri;
    shape->area();
    return 0;
}

C++ 类型转化
// (T)expre C 风格
// T(expre) 函数风格
/*

类可以向上转型,不能向下

void func(int *i){};
int main() {
    double d = 3.14;
    int a = (int)d;
    int b = int(d);
    int b1 = static_cast<int>(d);//c++
    int a1 = 3;
    const int b2 = (const int)a1;
    const int b3 = static_cast<const int>(a1);
    const int ad = 12;
//    func(&ad);//error
    func(static_cast<int *>(&a));
    int ma = 0x76;
    printf("a = %d,addr=%p,\n",ma,&ma);
    int *ap = &ma;
    char * mc = reinterpret_cast<char *>(ap);
    printf("c = %c,addr=%p,\n",*mc,&mc);

    return 0;
}

6. C++ 异常处理

异常demo 析构函数不要抛出异常

void f1()throw(int){
    cout << "f1 start" <<endl;
    int a;
    throw 2;
    cout << "f1 end" << endl;
}
void f2()throw(int){
    cout << "f2 start" <<endl;
    f1();
    cout << "f2 end" << endl;
}
void f3(){
    cout << "f3 start" << endl;
    try {
        f2();
    }catch(int i){
        cout << "exception :" << i << endl;
    }

    cout << "f3 end" << endl;
}

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

7. 友元函数

#include <iostream>
using namespace std;
class Test{
public:
    Test(){}
    Test(int a, int b) : a(a), b(b) {

    }

    friend void add1(Test t);

    void add(){
        a = a + b;
        cout << "a:" << a << endl;
    }
private:
    int a;
    int b;
};

void add1(Test t) {
cout << t.a << t.b<< endl;

}

int main() {
    Test test;
    add1(test);
    return 0;
}

//在类的外部类里面的私有的成员变量
//1. 友元函数是没有this指针的
//2. 你要访问的是类的非静态成员,需要对象做参数
//2. 你要访问的是类的静态成员,则不需要对象做参数
//3. 如果做参数的是全局对象,则不需要对象做参数

//为什么要设计友元函数 友元类
//1. java反射 直接修改类的私有属性
//2. 开了一个后门


#include <iostream>
#include <string.h>

using namespace std;//使用命名空间std标准的命名空间


//static
class Test{
public:
    void printC(){//成员函数 是不是可以使用静态变量 或者静态函数
        cout <<"c: " <<c<<endl;
        getC();
    }

    void addC(){
        c = c + 1;
    }

    static int getC(){//静态成员函数
        //静态成员函数 不能调用普通成员函数 或者普通成员变量
        cout << "c: " <<c<<endl;
//        cout << "a: " << a<<endl;
        return c;
    }


private:
    int a;
    int b;//成员变量是 是每个对象 都有一份
    static int c;//静态成员变量 类的多个对象共享
};


//1.
int Test::c = 1;


int main01(){
    //TODO: static
    cout<<"static"<<endl;
   //静态成员变量然后初始化
   Test t1;

   //静态成员函数调用
   //1.
   t1.getC();
//  Test::c = 10;
//    int Test::c = 1;//这里不能这么写
   //2
   Test::getC();

    return 0;
}



class Test1{

public:

    friend class Test2;//友元类 Test2是Test1的好朋友,
    //在Test2中可以访问Test1类的私有的成员变量,私有函数(private/protected)

    Test1(){

    }
    Test1(int a,int b){
        this->a = a;
        this->b = b;
    }


    void add(){
        a = a +b;
        cout << "a: " << a <<endl;
    }

    int c;

private:
    friend void add1(Test1 t);//友元函数的声明方式,友元函数
    friend void print1();
    int a;
    int b;
    static int d;
    void print(){
        cout <<"a: " << a<<" ,b: " <<b <<" ,c: "<<c<<endl;
    }
};

class Test2{

public:
    void setA(int a){//
        t1.c = a;
        t1.a= a;
    }

    void print(){
        cout <<"t1.a: " << t1.a<<endl;
        t1.print();
    }

private:
    Test1 t1;

};

Test1 gTest;

//在类的外部类里面的私有的成员变量
//1. 友元函数是没有this指针的
//2. 你要访问的是类的非静态成员,需要对象做参数
//2. 你要访问的是类的静态成员,则不需要对象做参数
//3. 如果做参数的是全局对象,则不需要对象做参数

//为什么要设计友元函数 友元类
//1.  java反射 直接修改类的私有属性
//2.  开了一个后门
void add1(Test1 t){
    t.a = t.a +t.b;
    cout << "a: " << t.a  <<t.c<<endl;
}

void print1(){
//  cout <<"gTest.a: " << gTest.a << Test1::d<<endl;
}


//类的友元函数
//1. 定义在类的外部
//2. 有权访问类的所有private/protected的成员
int main02(){
    //TODO: 友元函数 友元类
    cout<<"友元函数 友元类"<<endl;// << >> 原本的一样:位移  流的输入输出

    Test1 t1;
//     Test1::d = 10;
    Test2 t2;
    t2.setA(2);
    t2.print();


    return 0;
}

8. inline的用法和解释

9. C++ 函数运算符重载

10. C++ 静态函数

11. C++ 模板

模板demo

template <typename T>
void swap1(T& a,T&b){
    T temp(a);
    a = b;
    b = temp;
}

int main() {
    int i = 1;
    int j  = 2 ;
    swap1(i,j);
    cout << "i:" << i <<"j:" << j<< endl;
    float m = 3.0;
    float n = 4.0;
    swap1(m,n);
    cout << "m:" << m <<"n:" << n<< endl;

    return 0;
}
上一篇下一篇

猜你喜欢

热点阅读