C++基础03 const关键字、static关键字、拷贝构造函数、运算符重载、输入输出流的重载、异常处理、IO流

一、const关键字

const关键字修饰的代表是常量,只读,不可以修改,同时要求const对象必须初始化

#include "iostream"
using namespace std;

class Base{
//    修饰成员函数 表示这个函数只能调用const类型函数 并且在函数中不可以修改任何成员变量
    void fucntion1() const;
};

class Person{
    int age;
    const string name;
//    const修饰的成员变量只能通过初始化列表来构造
    Person(int age,string name):name(name){
        this->age=age;
    }
};
int main(){
//    const定义常量
    const double min=9.9;

//    修饰指针
    const int *p1;  // 靠int 比较近 所有指针p1 指向的值不可以修改
//    *p1=100;

    int const *p2;  // 靠p2 比较近 所有指针p1 指向的值不可以修改
//    *p2=13;

    int i=10;
    int * const p3=&i; // const靠近p3的位置,所以p3指向的地址不能变但是值可以变

    const int * const p4=&i; // p4指向的值和地址都不能变


    return 0;
}

二、static关键字

#include "iostream"
using namespace std;

/*
 * static 关键字
 * 静态变量的特点就是,当一个函数返回后,下一次调用的时候该变量会保持上次的值
 * 函数内部的静态变量值开辟一次空间,并且不会因为多次调用产生副本,也不会因为函数返回而生效
 *
 * 可以用于解决同一个类的不同对象的数据共享
 *
 * 使用类名::标识符的方式访问静态数据成员,因为静态数据成员不属于任何一个对象,修改的话,需要加类型
 * 对静态成员初始化要定义在类定义外进行
 *
 * 静态成员函数主要用于处理该类的静态数据成员,可以直接调用静态数据成员
 * 如果要访问非静态成员则需要对象来访问
 * 使用 类名::函数名 操作符来调用静态成员函数
 * 使用 类.函数名 调用
 */

class Person{
private:
    int age;
    static int score;
public:
    static void findPerson(Person perosn);
    Person(int age){
        this->age=age;
    }
    int getVisitors(){
        static int count = 0;
        return count++;
    }
};
int Person::score=10;

void Person::findPerson(Person perosn) {
    cout << "age:" << perosn.age << endl;
}
int main(){
    Person person1(18);
    cout << person1.getVisitors() <<endl;
    Person person2(18);
    cout << person2.getVisitors() <<endl;

    Person::findPerson(person1);

    return 0;
}

三、拷贝构造函数

在创建对象时,是使用之前创建的对象来初始化新创建的对象
如果类带有指针,并且动态内存分配,则必须有一个拷贝构造函数

如果在类中没有定义拷贝构造函数,编译器会自行定义一个
也可以自己写一个拷贝构造函数
//
// Created by KerwinWan on 2023/4/20.
//
#include <cstring>
#include "iostream"
using namespace std;

class Student{
private:
    int age;
    char *name;
public:
    void display(){
        cout << "age:" << age << " name:" << name << endl;
    }
    Student(char *n,int a){
        cout << "函数执行了" <<endl;
        age=a;
        name=n;
    }

    ~Student(){
        cout << "析构函数执行了" << endl;
        if (name!= nullptr){
            delete [] name;
            name=NULL;
        }
    }
//    自定义拷贝构造
    Student(const Student&s){
        cout << "自定义拷贝构造函数执行" << endl;
        age=s.age;
        int len=sizeof(s.name);
        name=new char[len+1];
        strcpy(name,s.name);
        name[len]='\0';
    }
};

int main(){
    Student s1("zwj1",20);
    s1.display();
    Student s2(s1);
    s2.display();


    return 0;
}

四、运算符重载

//
// Created by KerwinWan on 2023/4/24.
//
#include <cstring>
#include "iostream"
using namespace std;
/*
 * 运算符的重载 双目运算符重载
 * 运算符重载是重载系统内部的运算符函数,是实现静态多态性的方式之一,本质是函数重载
 *
 * 要求:不允许创造新的运算符,只能对已有的运算符重载
 * 不允许重载运算符有:成员运算符. 成员指针访问运算符.* 域运算符:: 求字节运算符sizeof 条件运算符?
 * 重载不能改变运算符运算对象的个数,比如+需要两个参数,不能只写一个参数
 * 重载不能改变运算符的优先级
 * 重载不能改变运算符的结合性
 * 重载的运算符必须和用户定义的自定义类型的对象一起使用,参数至少有一个类对象或引用
 */

class Complex{
private:
    int a;
    int b;
public:
    Complex(int a,int b){
        this->a=a;
        this->b=b;
    }
    void display(){
        cout << "a:" <<a << " b:" << b << endl;
    }

    Complex& operator+=(const Complex another){
        this->a+=another.a;
        this->b+=another.b;
        return *this;
    }
// 单目运算符重载
    int operator++(){

        return this->a+100;
    }
};
int main(){
    Complex c1(2,3);
    Complex c2(5,6);
    (c1+=c2).display();
    Complex c3(11,22);
    
    // 单目运算符重载后使用
    cout << c3.operator++() << endl;


    return 0;
}

五、输入输出流的重载

class Complex{
private:
    int a;
    int b;
public:
    Complex(int a,int b){
        this->a=a;
        this->b=b;
    }
    void display(){
        cout << "a:" <<a << " b:" << b << endl;
    }

    Complex& operator+=(const Complex another){
        this->a+=another.a;
        this->b+=another.b;
        return *this;
    }
// 单目运算符重载
    int operator++(){

        return this->a+100;
    }
 /*
 * 用户自己定义的类型的数据,是不可以直接用<<和>>来输入输出的,如果想想用这个来输入和输出自己定义的类型和数据 则必须要重载
 * cin 类型 istream类的对象
 * cout类型 ostream类的对象
 * 流运算符 >> <<
 * 必须采用友元函数的形式重载的原因
 * 1、这样就可以不创建对象直接调用函数
 * 2、输入输出流重载,不是类的成员,所以应该声明为类的友元函数

 * 构造参数
 * istream & operator >> (istream &,自定义类 &)
 * ostream & operator << (ostream &,自定义类 &)

 */
    friend ostream & operator<<(ostream &os,Complex &c);
    friend istream & operator>>(istream &is,Complex &c);

};
ostream & operator<<(ostream &os,Complex &c){
    cout << "自定义<<:" << endl;
    c.display();
    return os;
}
istream & operator>>(istream &is,Complex &c){
    cout << "请输入" <<endl;
    cin >> c.a >> c.b ;
    return is;
}

int main(){
    Complex c1(2,3);
    Complex c2(5,6);
    (c1+=c2).display();
    Complex c3(11,22);

    // 单目运算符重载后使用
    cout << c3.operator++() << endl;

    cin>>c1;
    cout<<c1;


    return 0;
}

六、异常处理


#include <cstring>
#include "iostream"
using namespace std;

/*
 * 程序运行的时候会出现异常
 * C++通过throw和try...catch进行异常处理
 * throw 语法如下 throw xxx      xxx为任何类型对象
 *
 * 还可以自定义异常对象
 * */
class MyException{
private:
    string message;
public:
    MyException(string message){
        this->message=message;
    }
    string getstring(){
        return message;
    }
};
void FunDiv(int a,int b){
    if (b==0){
        throw "除数不能为0";
    } else if(b==1){
        throw MyException("nonono");
    }
    cout << "is OK" << endl;
    int c=a/b;
}
int main(){
    try {
        FunDiv(1,1);
    }catch (char const* a){
        cout << a <<endl;
    }catch (int a){
        cout << a <<endl;
    }catch (double a){
        cout << a <<endl;
    } catch (MyException myException) {
        cout << myException.getstring() <<endl;
    }


    return 0;
}

七、IO流


#include <cstring>
#include "iostream"
#include "fstream"
using namespace std;
/*
 * 文件流的使用步骤
 * 1、定义一个文件流对象,输出文件流对象和输入文件流对象,输入输出针对内存而言
 * 2、使用文件流对象的成员函数打开一个磁盘文件,是的文件对象和磁盘文件之间建立连接
 * 3、使用提取和插入运算符对文件机械能读写,或使用成员函数进行读写
 * 4、关闭文件

 * 文件常见的打开方式
 * 1、in 以读的方式打开文件
 * 2、out以写的方式打开文件
 * 3、binary以二进制的方式对文件进行操作
 * 4、ate输出位置从文件的末尾开始
 * 5、app以追加的方式对文件进行写入
 * 6、trunc将文件内容清空再打开文件
 *
 * ifstream 用于从文件中读取 由istream派生而来

 * ofstream 用于将内容写到文件中 由ostream派生而来
 * */


int main(){
//    ifstream 对象名(文件路径,打开方式)
//    ifstream file1("name.text",ios::in);
    ifstream fin;
    fin.open("/name.txt",ios::in);
//    seekg方法 找相对位置  参数为 偏移量和位置指示 
//    ios_base::beg 文件的开始位置 
//    ios_base::cur 当前位置 
//    ios_base::end 文件结尾
    fin.seekg(2,ios_base::beg);
    char buffer[256];
//    第一个参数 读到哪里,第二个是读多少个
    while (fin.getline(buffer,256)) {
        cout << buffer << endl;
    }

//  方式二
    ofstream fout;
    fout.open("/name.txt",ios::out);
    fout << "hello1111111111111afafaffasfsa1111111"<<endl;

    fin.close();
    fout.close();

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值