C++ 基础代码模板和使用

作者: zcwfeng | 来源:发表于2021-03-20 06:45 被阅读0次

C 语言不支持函数重载,C++才支持

int add(int num1, int num2) {
    return num1 + num2;
}

int add(int num1, int num2, int num3) {
    return num1 + num2 + num3;
}

C++ 11 的 Auto

类型推断,不指定变量类型,编译器根据初始值给定类型。
auto n = 0;//int
auto x = 0.0;//double
auto y = 1.3e12L;//long double

auto 处理复杂类型推断比较有明显作用,普通变量没必要。如在stl中的使用

void testSTL(){
    std::vector<double> score;
    std::vector<double>::iterator pv = score.begin();
    auto pv2 = score.begin();
}

C++11 vector array

int main(){
    double a1[4] = {1.2,2.4,3.6,4.8};

    vector<double> a2(4);
    a2[0]=1.2;
    a2[1]=2.4;
    a2[2]=3.6;
    a2[3]=4.8;
    array<double,4> a3={1.2,2.4,3.6,4.8};
    array<double,4> a4;
    a4 = a3;

    cout << "a1[2]: " << a1[2] << " at " << &a1[2] << endl;
    cout << "a2[2]: " << a2[2] << " at " << &a2[2] << endl;
    cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
    cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;

    cout << "-------------" << endl;
    a1[-2] = 20.2;
    cout << "a1[-2]: " << a1[-2] << " at " << &a1[-2] << endl;
    cout << "a3[2]: " << a3[2] << " at " << &a3[2] << endl;
    cout << "a4[2]: " << a4[2] << " at " << &a4[2] << endl;

    cout << "a4[2]: " << a4.at(2) << " at " << &a4.at(2) << endl;
    cout << "a4[2]: " << *(a4.begin() + 2) << " at " << &(*(a4.begin() + 2)) << endl;

//    a2.at(2);a2.begin();a2.end();

    return 0;
}

除了赋值,和使用,begin(),end(),at() 优化了数组越界的隐患。

判断文件的结尾 EOF

<iostream> 定义EOF 是文件的结尾

字符函数库 <cctype>

char ch = 'r';
isalpha(ch) 是否为字母字符
isdigit(ch) 是否是数字字符
isspace(ch) 是否是空白换行等
ispunct(ch) 是偶是标点符号

引用变量

int rat = 10;
int &rat2 = rat;
cout << "rat:" << rat << "--rat2:" << rat2 << endl;
rat2 = 100;
cout << "rat:" << rat << "--rat2:" << rat2 << endl;

模板方法

template <typename T>
void Swap(T &a,T &b);
int main() {
    int i = 10;
    int j=120;
    Swap(i,j);
    cout << "i:" << i << "--j:" << j << endl;

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

template <typename T>
void Swap(T *a,T *b,n);

定义操作数组模板

命名空间

namespace zcwfeng{
    class Top{
    }
}

using namespace zcwfeng;
命名空间嵌套

namespace zcwfeng2{
    namespace inner{
        namespace inner2{
            void out(){
                
            }
        }
    }
}
using namespace zcwfeng2::inner::inner2;

读入,写出 <iostream>

cin.getline
cin.clear
cout<<endl;
get() 面向行输入

新增数据类型,和使用

wchar_t title[] = L"wchar test";
    char16_t name[] = u"name test16";
    char32_t name2[] = U"name test32";

公用体 Union

union one4all{
    int intval;
    long longval;
    double doubleval;
} pail;

共用体的长度为其最大成员的长度。(pail有时可以是int,有时double,共用体只能存储一个值,因此必须有足够控件存储最大成员)
当数据使用两种或者以上多种格式可以节省空间。如某些商品ID是整数,有一些是字符串。

typedef struct widget{
    char brand[20];
    int type;
    union {
        long id_num;
        char id_char[20];
    };
} prize;

公用提是匿名的,因此id_num和id_char 视为两个成员,他们的地址相同。所以不需要中间标识符 ,我们自己负责那个成员是活动的。
共用体常用(并非只能用于)节省内存。并非所有的四通都是现在这种大存储系统GB甚至TB级别。烤箱,mp3 等处理器内存节省就比较重要。公用体常用系统数据结构或硬件数据结构。

常量指针,和指针常量

    int number = 9;
    int number2 = 8;

    // 常量指针
    const int * numberP1 = &number;
    // *numberP1 = 100; // 报错,不允许去修改【常量指针】存放地址所对应的值
     numberP1 = &number2; // OK,允许重新指向【常量指针】存放的地址

    //  指针常量
    int* const numberP2 = &number;
    *numberP2 = 100; // OK,允许去修改【指针常量】存放地址所对应的值
    // numberP2 = &number2; // 报错,不允许重新指向【指针常量】存放的地址

    // 常量指针常量
    const int * const numberP3 = &number;
    // *numberP3 = 100; // 报错,不允许去修改【常量指针常量】存放地址所对应的值
    // numberP3 = &number2; // 报错,不允许重新指向【常量指针常量】存放的地址

浅拷贝和深拷贝

默认拷贝函数,是浅拷贝,如果想要深拷贝需要手动处理

如果有堆成员,必须实现深拷贝。

-> 头文件
#ifndef TEMPC_DEMO_H
#define TEMPC_DEMO_H

#include <iostream>
#include <string>
using namespace std;

namespace PeopleN{
    class People{
    public:

        People(int age, string &name) : age(age), name(name) {
            this->name = name;
            this->age = age;
            this->nickName = static_cast<char *>(malloc(sizeof(char) * 10));
            cout << "两个参数构造函数" <<endl;
        }

//        explicit People(int age) : age(age) {
//            cout << "一个参数构造函数" <<endl;
//        }

        explicit People(int age) : People(age,name="") {
            cout << "一个参数构造函数" <<endl;
        }

        virtual ~People() {
            cout << "析构!People"<<endl;
            //free 不能在c++使用,不会调用析构
            if(this->nickName){
                free(nickName);
                nickName = NULL;
            }
        }


        void test();

        int getAge() {
           return this->age;
        }

        const string &getName() {
            return this->name;
        }



        void setAge(int age) {
            this->age = age;
        }

        void setName(const string &name) {
            this->name = name;
        }


    private:
        int age;
        string name;
        char * nickName;
    };
}
#endif //TEMPC_DEMO_H

实现

People::People(int age, const string &name) : age(age), name(name) {

}

注意创建对象
new---delete 成对的写

auto people = new People(11);// 堆空间
delete people;
people = NULL;

共有继承和私有继承

private 继承在类内可以访问父类成员,外部不可以
public 集成 在类外也可以访问父类成员
父类可以给子类成员初始化

多继承
钻石问题,骡子问题

  1. 专门指定父类 :: 明确指定
  2. 重写父类 X不推荐
  3. virtual 声明父类方法

C++ 可变参数

#include <iostream>
#include <stdarg.h> // 可变参数的支持
using namespace std;

// Java的可变参数: int ...
// C++的可变参数写法:...
// count的第一个用处:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
void sum(int count, ...) {
    va_list vp; // 可变参数的动作

    // 参数一:可变参数开始的动作vp
    // 参数二:内部需要一个 存储地址用的参考值,如果没有第二个参数,内部他无法处理存放参数信息
    va_start(vp, count);

    // 到这里后:vp就已经有丰富的信息

    // 取出可变参数的一个值
    int number  = va_arg(vp, int);
    cout << number << endl;

    // 取出可变参数的一个值
    number  = va_arg(vp, int);
    cout << number << endl;

    // 取出可变参数的一个值
    number  = va_arg(vp, int);
    cout << number << endl;

    // 越界 系统值 乱码
    // 取出可变参数的一个值 【娶不到后,会取系统值 乱码】
    number  = va_arg(vp, int);
    cout << number << endl;

    // 关闭阶段
    va_end(vp);
}

// 1.可变参数
int main() {
    std::cout << "同学们大家好,我是Ferry" << std::endl;

    sum(546, 6,7,8);

    return 0;
}

循环取值和结束标记va_end

void sum(int count, ...) {
    va_list vp;//可变参数
    va_start(vp, count);

    int i;
    for (i = 0; i <count; ++i) {
        int number = va_arg(vp, int);
        cout << number << endl;
    }

    va_end(vp);


}

int main() {
    sum(4, 6, 7, 8, 9);
    return 0;
}

static 关键字

  1. 可以直接通过类名::静态成员(字段/函数)
  2. 静态的函数只能取操作静态的属性和方法(同Java)
  3. 静态的属性必须要初始化,然后再实现(规则)
/**
 * 静态的总结:
 * 1.可以直接通过类名::静态成员(字段/函数)
 * 2.静态的属性必须要初始化,然后再实现(规则)
 * 3.静态的函数只能取操作静态的属性和方法(Java)
 */

#include <iostream>

using namespace std;

class Dog {
public:
    char * info;
    int age;

    // 先声明
    static int id;

    static void update() {
        id += 100;

        // 报错:静态函数不能调用非静态函数(Java)
        // update2();
    }

    void update2() {
        id = 13;
    }
};

// 再实现
int Dog::id = 9;

int main() {
    Dog dog;
    dog.update2(); // 普通函数
    Dog::update(); // 静态函数
    dog.update(); // 对象名.静态函数(一般都是使用::调用静态成员,这种方式可以 知道就行)

    cout << Dog::id << endl;
    return 0;
}

方法+const

void test const{
}

相当与常量指针常量,只读

1. 常量引用不能改

typedef struct {
    char name[10];
    int age;
} Student;
// 常量引用不能改
void insertStudent(const Student & student){
//    只读
//    strcpy(student.name,"dfas");
}
int main(){
    Student student = {"张无忌",30};
    insertStudent(student);
    cout << student.name << ":"<<student.age<<;
}

2. 引用传递和指针的区别

void numberChange(int *number1,int *number2){
    cout<< "numberChange"<< "num1-addr:"<< &number1 <<",num2-addr:"<< &number2<<endl;

    int temp = 0;
    temp = *number1;
    *number1 = *number2;
    *number2 = temp;
}

void numberChange2(int & number1,int & number2){
    cout<< "numberChange2" <<"num1-addr:"<< &number1 <<",num2-addr:"<< &number2<<endl;

    int temp = 0;
    temp = number1;
    number1 = number2;
    number2 = temp;
}

int main1(){

    int number1 = 10;
    int number2 = 20;
    cout<< "num1-addr:"<< &number1 <<",num2-addr:"<< &number2<<endl;

    numberChange(&number1,&number2);
//    numberChange2(number1,number2);
    cout<< "num1:"<< number1 <<",num2:"<< number2<<endl;
    return 0;
}

3. 默认形参

int add(bool isOK = 0){
    
}

4. 开源框架的一些写法

这个样写是当前没想好,为了留下扩展使用

void uploadToEngine(char * LogText,int ){
    
}

5. 释放对象

new-delete

    Student student1;//栈空间
    Student * student = new Student();// 堆空间
    if(student){
        delete student;
        student = NULL;
    }

当然和c语言一样也有

6. 内联函数

inline 加上了,并不是所有的编译器起作用。知识在一定成都上做了优化,内联函数不能递归,优化C语言宏定义不能作为值传递问题。

7. 友元函数

访问内部私有成员。

8. 运算符重载 operator

一般习惯性写在类内部,可以借用this指针,也可以直接获取内部私有成员
参考系统写法,参数一般 【const 类 & 别名】

  1. 原因可以提高速度
  2. & 别名,只是创建副本引用
  3. const 限定不能随便调用函数更改

9. 源码中属性初始化的方式。

#include <iostream>
using namespace std; // 已经声明了

// 人类
class Person {
protected:
    // 注意:string 是 std 命名空间里面的成员,C++源码是这种写法std::string
    // string内部其实就是对 char*的封装
    string name;
    int age;
public:
    Person(string name, int age) :name(name), age(age) {}
};

// 课程类
class Course {
private:
    string name;
public:
    Course(string name) :name(name) {}
};

class Student : public Person {
private:
    // 如果定义的是对象成员,必须这样初始化(构造函数的后面 : 对象成员(内容))  使用我们的第二种方式
    Course course; // 对象成员
public:
    Student(string name, int age, Course course1, string courseNameInfo)
    :Person(name, age) // 既然继承了父类就必须给父类的构造函数初始化

    // ,

    // course(course1) // 第二种方式,编译阶段认可的 对象=对象   对象直接的赋值而已

     ,

     course(courseNameInfo) // 第三种方式, 对象(string内容)  直接初始化Course对象 --- 构造函数

    {
        // this->course = course1; // 第一种方式(对象=对象) 编译阶段不认可,无法监测到你是否真的给course对象成员初始化了
    }
};

int main() {
    Course c("C++");
    Student student("David", 30, c, "NDK内容真多");

    return 0;
}

相关文章

网友评论

    本文标题:C++ 基础代码模板和使用

    本文链接:https://www.haomeiwen.com/subject/wfnbqltx.html