自学内容网 自学内容网

C++知识回顾

使用C++进行算术运算:

#include <iostream>

using namespace std;

int main()
{
    int a = 0;
    int b = 0;
    char c = 'e';
    int ret = 0;
    while(1)
    {
        cout << "请输入要计算的两个数字:" << endl;
        cin >> a;
        cin >> b;
        cout << "请输入运算法则:+、-、*、/" << endl;
        cin >> c;
        switch (c)
        {
        case '+' :
            ret = a + b;
            break;
        case '-':
            ret =a - b;
            break;
        case '*':
            ret = a * b;
            break;
        case '/':
            ret = a / b;
            break;
        default:
            ret = 0;
            break;
        }
        cout << "计算结果:" << endl;
        cout << ret <<endl;
    }
    return 0;
}

C++中结构体的使用:

#include <stdio.h>
#include <stdlib.h>
struct car
{
    char *corlor;
    char *id;
    void (*printInfo)(char *corlor,char*id);
};
void printInfo(char *a,char *b)
{
    printf("corlor:%s\nid:%s\n",a,b);
}
int main()
{
    struct car mycar;
    mycar.corlor = "black";
    mycar.id     = "京A888888";
    mycar.printInfo = printInfo;

    struct car mycar2 ={
        .corlor = "white",
        .id     = "京A666666",
        .printInfo = printInfo,
    };

    struct car *mycar3;
    mycar3 = (struct car *) malloc(sizeof(struct car));
    mycar3 ->id = "冀A88888888";
    mycar3 ->corlor = "blue";
    mycar3 ->printInfo =printInfo;

    mycar.printInfo(mycar.corlor,mycar.id);
    mycar2.printInfo(mycar2.corlor,mycar2.id);
    mycar3->printInfo(mycar3->corlor,mycar3->id);
    return 0;
}

C++中类的使用:

#include <string>
#include <iostream>

using namespace std;

class car
{
public:
    string corlor;
    string id;
    void (*printInfo)(string corlor,string id);     //这个是函数指针变量
    void printCarInfo()  //成员函数在内部实现
    {
        cout << "成员函数打印" << endl;
        cout << "汽车颜色:" << corlor << "汽车车牌号" << id <<endl;
    }
    void printCarInfo2();  //成员函数在内部声明,一般在.cpp文件里面实现class中声明的函数
};

void car :: printCarInfo2()
{
    cout << "成员函数在外部实现" << endl;
}
void printInfo(string a,string b)
{
    string ret = "颜色:" + a +"车牌号:" + b;
    cout << ret <<endl;

}
int main()
{
    car mycar;
    mycar.corlor = "black";
    mycar.id     = "京A888888";
    mycar.printInfo = printInfo;

    car mycar2 ={
        .corlor = "white",
        .id     = "京A666666",
        .printInfo = printInfo,
    };

    car *mycar3 = new car();
    mycar3 ->id = "冀A88888888";
    mycar3 ->corlor = "blue";
    mycar3 ->printInfo =printInfo;

    mycar.printInfo(mycar.corlor,mycar.id);
    mycar2.printInfo(mycar2.corlor,mycar2.id);
    mycar3->printInfo(mycar3->corlor,mycar3->id);

    cout << "下面是成员函数输出内容:" << endl;
    mycar.printCarInfo();
    mycar2.printCarInfo();
    mycar3->printCarInfo();
    mycar.printCarInfo2();
    mycar2.printCarInfo2();
    mycar3->printCarInfo2();
    return 0;
}

C++引用的使用

#include <iostream>

using namespace std;
void swap(int& c,int& d)
{
    int temp;
    temp = c;
    c = d;
    d =temp;
}

double vals[] = {1.1,1.2,1.3};
double& setvalue(int i)
{
    double &ref = vals[i];
    return ref;
}

//int& getdata()
//{
//    int a = 10 ,b = 10;
//    int& ra = a;
//    return ra;  //当返回一个引用时,要注意被引用的对象不能超出作用域,所以返回一个局部变量的的引用是不合法的(函数调用完就将空间释放了),可以返回一个静态变量的引用。
//}
int main()
{
    int a = 10;
    int b = 20;

    cout << "交换之前:" << endl;
    cout << "a =" << a <<endl;
    cout << "b =" << b <<endl;

    swap (a,b);

    cout << "交换之后:" << endl;
    cout << "a =" << a <<endl;
    cout << "b =" << b <<endl;


    setvalue(2) = 10.5;    //其实就是函数返回vals[2]的引用,就是vals[2]的别名,然后对别名进行操作就是对其本身进行操作,所以引用可以当左值
    cout << vals[2] <<endl;

    return 0;
}
#include <iostream>

//引用变量是一个别名,也就是说,他是某个已经存在变量的另一个名字
//引用相当于又给这个内存中的数据提供了一个新的变量名,这个变量名比传统数据名更特殊,是直达地址的

/*
引用与指针的区别:
1、不存在空引用,引用必须连接到一块合法的内存
2、一旦引用被初始化一个对象,就不能被指向另一个对象,指针可以在任何时候指向另一个对象
3、引用必须在创建的时候初始化,指针可以在任何时间初始化
4、官方没有明确说明,但是引用确实不是传统意义上的独立变量,他不可以“变”
5、引用和指针一样也区分类型
*/

using namespace std;

int main()
{
    //声明简单的变量
    int i;
    double d;

    //声明引用变量
    int& r = i;
    double& s = d;

    i = 5;

    cout << "value of i:"<< i << endl;
    cout << "refrence of i:" << r <<endl;

    d = 10.121;

    cout << "value of d:"<< d << endl;
    cout << "refrence of d:" << s <<endl;


    cout << "Hello World!" << endl;
    return 0;
}

C++自定义命名空间

  • main.cpp
#include <iostream>
#include "namespace_my.h"
using namespace std;
//using namespace cir;

int main()
{
    double r = 7;
//    cout << getLenthOfCir(r) << endl;
    cout << cir::getLenthOfCir(r) <<endl;
    cout << "Hello World!" << endl;
    return 0;
}
  • mynamespace.h
#ifndef NAMESPACE_MY_H
#define NAMESPACE_MY_H

namespace cir
{
    double PI = 3.141592653;
    //获取圆形周长
    double getLenthOfCir(double r)
    {
        return 2*PI*r;
    }

}
#endif // NAMESPACE_MY_H

C++函数重载

#include <iostream>

using namespace std;

class printData
{


public:
    void print(int i);
    void print(double i);
    void print(string c);

};
//函数重载,要求传参类型/传参个数/传参顺序不同,函数名相同,不能仅仅函数返回值不同。
void printData ::print(int i)
{
    cout << "整型:" << i <<endl;
}

void printData ::print(double i)
{
    cout << "浮点型:" << i <<endl;
}
void printData ::print(string c)
{
    cout << "字符串:" << c <<endl;
}
int main()
{
    printData *printInfo;
    printInfo = new printData();
    printInfo->print(1);
    printInfo->print(3.1415926);
    printInfo->print("hello world");
    return 0;
}

new和delete的使用、构造函数说明

#include <iostream>

using namespace std;

//new 关键字用于动态分配内存,他是C++中处理动态内存分配的主要工具之一,允许程序运行时根据需要分配内存

/*
注意事项:
1、异常安全:如果new分配内存失败,他会std::bad_alloc异常(除非使用了nothrow版本)
2、内存泄漏:忘记释放new分配的内存会导致内存泄露
3、匹配使用delete 和delete[]:为避免未定义行为,使用new分配的单个对象应该使用delete释放,分配的数组应该使用delete释放

delete ptr  ---释放ptr指向的对象
delete[] ptr ---释放ptr指向的数组

*/


class My
{

public:

    //构造函数会在每次创建类的新对象时执行
    //构造函数类的名称与类名是完全相同的,并且不会返回任何类型,也不会返回void,构造函数可以为某些成员变量设置初始值
    My()
    {
        cout << "构造函数" <<endl;
    }
};
int main()
{
    //分配单个对象
    My *point = new My();

    //分配对象数组
    int* myArray = new int[5]{1,2,3,4,5};  //数组内容初始化为1,2,3,4,5

    delete point;
    delete[] myArray;


    cout << "Hello World!" << endl;
    return 0;
}

static关键字

#include <iostream>

using namespace std;

//静态成员在C++中是一个重要的概念,它包括静态成员变量和静态成员函数

/*
静态成员变量:
1、定义:静态成员变量是类的所有对象共享的变量,与普通变量相比,无论创造了多少个类的实例,静态成员变量只拷贝一份;
2、初始化:静态成员变量需要在类外进行初始化,通常在类的实现文件夹中;
3、访问:静态成员变量可以通过类名直接访问,不需要创建类的对象,也可以通过类的对象访问;
4、用途:常用于存储类级别的信息(例如:计数类的实例数量)或全局数据需要被类的所有实例共享

静态成员函数:
1、定义:静态成员函数是可以不依赖于类的实例而被调用的函数,她不能访问类的非静态成员变量和非静态成员函数;
2、访问:类似于静态成员变量,可以通过类名直接访问,也可以通过类的实例调用;
3、用途:常用于实现与具体对象无关的功能,或访问静态成员变量

*/

class Myclass
{
public:
    int data;
    static int count_value;   //静态成员变量
    Myclass ()
    {
        count_value++;
    }

    static int getValue()     //静态成员函数,在创建对象之前就已经存在的
    {
        //data++;   静态成员函数不能访问非静态成员变量
        return count_value;
    }
};

int Myclass :: count_value = 0;

int main()
{
    Myclass my1;
    Myclass my2;

    cout << Myclass :: count_value << endl;  //使用类名直接访问
    cout << Myclass :: getValue() << endl;  //使用类名直接访问
    return 0;
}

this关键字

#include <iostream>

using namespace std;

//this关键字是一个指向调用对象的指针,他在函数内部使用,用于引用调用该函数对象。
//使用this可以明确指出成员函数正在操作的是哪个对象的数据成员
//可以使用this指针返回当前对象的引用

class Car
{
private:
    string brand;
    int year;
public:
    Car(string brand,int year)
    {
        this->year = year;
        this->brand =brand;
    }
    void print()
    {
        cout << "汽车品牌:" << brand <<endl;
        cout << "年限:"    << year  <<endl;
        cout << this <<endl;
    }

    Car& setYear(int year)
    {
        this->year = year;
        return  *this;     //可以使用this指针返回当前对象的引用,*是取内容。
    }

};

int main()
{
    Car baoma("宝马", 20);
    baoma.print();

    baoma.setYear(10).print();   //链式调用————可以在setYear后面直接调用.print()
    cout << &baoma <<endl;
    return 0;
}

析构函数

#include <iostream>

using namespace std;

//析构函数时C++中的一个特殊成员函数,他在对象生命周期结束时被自动调用,用于执行对象销毁前的清理工作。
//析构函数尤为重要尤其涉及动态分配的资源(如:内存、文件句柄、网络连接等)

/*
基本特性:
1、名称:析构函数的名称由~和类名构成
2、无返回值和参数:析构函数不要任何参数和返回值
3、自动调用:当生命周期结束时(例如:一个局部作用域结束时,或者delete删除一个动态分配的对象时),析构函数也会被自动调用
4、不可重载:每个类只有一个析构函数
5、继承和多态:如果一个类是基类,其析构函数应该是虚的
*/

class Myclass
{
private:
    int *data;
public:
    Myclass(int size)
    {
        data = new int[size];   //给类中的指针开辟空间
    }
     ~Myclass()
    {
        cout << "析构函数被调用" << endl;
        delete [] data;  //通过析构函数释放类中申请的空间
    }
};

int main()
{
    Myclass my1(5);


    Myclass *my2 = new Myclass(10);

    delete  my2;  //调用delete时析构函数被调用

    cout << "Hello World!" << endl;
    return 0;
}

lambad表达式

#include <iostream>

using namespace std;

/* lambad表达式是C++引入的一种匿名函数的方式,他允许你在需要函数的地方内联定义函数,而无需单独命名函数*/
/*
lambad表达式的语法:
[caputure clause] (param) ->return_type
{
    //函数体
    //可以捕获列表中的变量
    return expression;  //可选的返回语句
}


[caputure clause] :是捕获列表,用于捕获外部变量,捕获列表可以为空,也可以包含变量列表
(param):参数列表,与普通的参数列表类似,可以为空或包含参数列表
return_type:lambad表达式可以自动推断(atuo)返回类型,也可以显式指定返回类型,如果函数只有一条语句,可以省略返回类型。
*/

/*
int add(int a, int b)
{
    return a + b;
}
*/

bool compare(int a, int b)
{
    return a > b;
}

int getMax(int a, int b, bool (*p_compare)(int ,int))
{
    if (p_compare(a, b))
    {
        return a;
    }
    else
    {
        return b;
    }
}

int main()
{
    int x=10, y=20;
    int ret =0;
    auto add = [](int a, int b) ->int
    {
        return a + b;
    }; //lambad是匿名函数,指向add,auto表示预测add函数的返回值,虽然->后面指定了返回值类型是int,但是还是要写上auto预测返回值。
    ret = add(x,y);

    int max1 = getMax(y,x,compare);


    int max2 = getMax(y,x, [](int a, int b) ->bool    //使用lambad匿名函数替换函数指针
    {
        return a > b;
    });
    cout << ret << endl;
    cout << max1 << endl;
    cout << max2 << endl;
    return 0;
}
#include <iostream>

using namespace std;

//lambad函数适用于一次性的函数,在定义的作用域内有效,内联函数在整个程序运行周期有效。
int main()
{
    int x = 10, y = 20;
    int ret = 0, ret2 = 0, ret3 = 0;
    auto add = [x, y]() ->int
    {
        //x++;
        //y++;   这种方式捕获,是不能修改变量值的,只能用,不能修改,只读

        return x + y;
    };

    ret = add();  //使用捕获参数列表的方式,不传入形参变量,在调用add()的时候不用传入形参
    cout << ret << endl;



    auto add2 = [=]() ->int   //在捕获列表中填写 = 表示将前面所有的变量都捕获进来,不写要在捕获列表中写明变量
    {
        //x++;
        //y++;   这种方式捕获,是不能修改变量值的,只能用,不能修改,只读
        return x * y * ret;
    };

    ret2 = add2();  //使用捕获参数列表的方式,不传入形参变量,在调用add()的时候不用传入形参
    cout << ret2 << endl;

    //使用引用的方式来捕获时(引用类似指针),进行地址访问,可以修改捕获列表里面的变量
    auto add3 = [&]() ->int   //在捕获列表中填写 = 表示将前面所有的变量都捕获进来,不写要在捕获列表中写明变量
    {
        x++;
        y++;   //引用方式进行变量的捕获时,可以修改捕获列表里面的数值,&表示捕获所有变量,可读可修改
        return x * y;
    };

    ret3 = add3();  //使用捕获参数列表的方式,不传入形参变量,在调用add()的时候不用传入形参
    cout << ret3 << endl;
    cout << x << endl;
    cout << y << endl;  //通过引用的方式捕获变量后,修改后会影响lambad函数外面的变量值
    return 0;
}

C++的类的组合知识

#include <string>
#include <iostream>

//在C++中一个类包含另一个类的对象成为组合(composition)
using namespace std;
class Wheel
{
public:
    string brand;
    string year;
    void printWheel();
};
void Wheel :: printWheel()
{
  cout << "轮胎品牌是:" << brand <<endl;
  cout << "轮胎年限是:" << year <<endl;
}

class car
{
public:
    string corlor;
    string id;
    Wheel luntai;   //在C++中一个类包含另一个类的对象成为组合(composition)
    Wheel * p_luntai;
    void (*printInfo)(string corlor,string id);     //这个是函数指针变量
    void printCarInfo()  //成员函数在内部实现
    {
        cout << "成员函数打印" << endl;
        cout << "汽车颜色:" << corlor << "汽车车牌号" << id <<endl;
    }
    void printCarInfo2();  //成员函数在内部声明,一般在.cpp文件里面实现class中声明的函数
};

void car :: printCarInfo2()
{
    cout << "成员函数在外部实现" << endl;
    luntai.printWheel();
    p_luntai ->printWheel();
}
void printInfo(string a,string b)
{
    string ret = "颜色:" + a +"车牌号:" + b;
    cout << ret <<endl;

}
int main()
{
    car mycar;
    mycar.corlor = "black";
    mycar.id     = "京A888888";
    mycar.printInfo = printInfo;
//    mycar.luntai.brand = "宝马";
//    mycar.luntai.year = "20";
    mycar.p_luntai = new Wheel();
    mycar.p_luntai->year = "20";
    mycar.p_luntai->brand = "宝马";

    car *mycar3 = new car();
    mycar3 ->id = "冀A88888888";
    mycar3 ->corlor = "blue";
    mycar3 ->printInfo =printInfo;
//    mycar3->luntai.year = "30";
//    mycar3->luntai.brand = "奔驰";
    mycar3->p_luntai = new Wheel;  //实例化对象的时候,不用括号也可以
    mycar3->p_luntai->year = "15";
    mycar3->p_luntai->brand = "奔驰";

    mycar.printInfo(mycar.corlor,mycar.id);
    mycar3->printInfo(mycar3->corlor,mycar3->id);

    cout << "下面是成员函数输出内容:" << endl;
    mycar.printCarInfo();
    mycar3->printCarInfo();
    mycar.printCarInfo2();
    mycar3->printCarInfo2();
    return 0;
}

C++有关bool类型说明

#include <iostream>

using namespace std;

int main()
{
    //c语言在C99以前是不支持boo类型l的,在c99之后支持bool类型,C++是支持的
    bool flag = false;
    int a = 0;
    int b = 0;
    if (!flag)
    {
        cin >> a >> b;
    }
    cout << a << b << endl;
    cout << "Hello World!" << endl;
    return 0;
}

C++中的虚函数

#include <iostream>

using namespace std;

//virtual 和override 关键字用于支持多态,尤其是在涉及类继承和方法重写的情况下

/*
virtual关键字

1、使用场景:在基类中声明函数
2、目的:允许派生类重写该函数实现多态
3、行为:当通过基类的指针或引用调用一个虚函数时,调用的是对象实际类型的函数版本(就是调用基类重写后的函数)


override关键字
1、使用场景:在派生类中重写虚函数;
2、目的:明确指示函数意图重写基类的虚函数;
3、行为:确保派生类的函数确实重写了基类中的一个虚函数


注意:
1、只在派生类中使用override:override仅用于派生类中重写基类的函数;
2、虚析构函数:如果类中有虚函数,通常应该将析构函数也声明为虚的;
3、默认情况下,成员函数不是虚的:只有显式使用virtual关键字才会成为虚函数;
4、继承中的虚函数:一旦基类中声明为虚函数,该函数在所有派生类中自动成为虚函数,无论是否使用virtual关键字。
*/
class Car
{
public:
    virtual void move()    //在基类中声明虚函数
    {
        cout << "基类中的函数" << endl;

    }
    virtual ~Car()
    {

    }

    virtual void run() = 0; //纯虚函数
};

class BBA : public Car
{
public:
    void move() override;   //在派生类中重写虚函数
};

void BBA :: move()
{
    cout << "在派生类中重写虚函数" << endl;
 }

int main()
{
    BBA baoma;
    baoma.move();

    Car car1;
    car1.move();
    cout << "Hello World!" << endl;
    return 0;
}

C++初始化列表的使用

#include <iostream>

using namespace std;

//在C++中使用初始化列表来初始化类的字段是一种高效的初始化方式,尤其是在构造函数中。初始化列表直接在对象的构造过程中初始化成员变量,
//而不是先创建成员变量再赋值,这对于提高性能尤为重要,特别是在涉及到复杂对象或引用和常量成员的情况下
/*

初始化列表的有点包括:
1、效率:对于非本类型的对象,使用初始化列表比在构造函数体内赋值更高效,因为他避免了先从默认构造然后再到赋值的额外开销;
2、必要性:对于引用类型和常量类型的成员变量,必须使用初始化列表,因为这些类型成员在构造函数体内不能被赋值;
3、顺序:成员变量的初始化顺序是按照他们在类中声明的顺序,而不是初始化列表中的顺序。
*/
class MyClass
{
private:
    int a;
    double b;
    string c;
public:
    MyClass (int temp_a,double temp_b,string temp_c)   //构造函数
    {
        a = temp_a;
        b = temp_b;
        c +temp_c;
        cout << "构造函数被调用" << endl;
    }
    MyClass (int temp_a,string temp_c): a(temp_a), c(temp_c)   //参数列表的使用方法,一般初始化列表写的顺序和类中声明的顺序相同,否则会有警告。
    {
        cout << "参数列表的方式进行构造" << endl;
    }
    void pint()
    {
        cout << a <<endl;
        cout << b <<endl;
        cout << c <<endl;
    }
};

int main()
{
    MyClass data(1,1.2,"普通构造函数传参");
    MyClass data2(1,"参数列表方式进行构造传参");

    data.pint();
    data2.pint();

    return 0;
}

C++菱形继承

#include <iostream>

using namespace std;

//菱形继承:如果两个基类继承自同一个更高层的基类,这可能导致派生类中存在两份基类的副本,称为菱形继承,可以通过虚继承来解决

/*
class Base
{

};

class A : public Base
{
    //继承自Base
};

class B : public Base
{
    //继承自Base
};

class C : public A, public B
{
    //继承自A,B
};                                  //菱形继承
*/

class Base
{
public:
    int data;
    Base(int temp_data)
    {
        this->data = temp_data;
    }
    void print1()
    {
        cout << data << endl;
    }
};

class A : virtual public Base
{
public:
    //继承自Base
    A(int data)  : Base(data)    //当父类有构造函数的时候要继承父类的构造函数
    {
        data = 20;
    }
    void print2()
    {
        cout << data << endl;
    }
};

class B : virtual public Base   //虚继承,来解决菱形继承的问题
{
public:
    //继承自Base
    B(int data)  : Base(data)    //当父类有构造函数的时候要继承父类的构造函数
    {
        data = 30;
    }
    void print3()
    {
        cout << data << endl;
    }
};

class C : public A, public B
{
public:
    //继承自A,B
    C(int data)  : Base(data),A(data),B(data)   //当父类有构造函数的时候,派生类的构造函数要继承其所继承父类的构造函数,并且要按照顺序继承
    {
//        this->data = data;
    }
};                                  //菱形继承

int main()
{

    C c(50);
    c.print1();
    c.print2();
    c.print3();
    return 0;
}

C++继承知识

  • main.cpp
#include <iostream>
#include "animal.h"
#include "cat.h"
using namespace std;

int main()
{
    Animal dog;
    dog.move();

    cat cat1;
    cat1.name = "è";
    cat1.move();
    cat1.favorite();

    cout << "Hello World!" << endl;
    return 0;
}
  • animal.cpp
#include "animal.h"

Animal::Animal()
{

}
void Animal:: move()
{
    cout << "移动" << endl;
}
  • animal.h
#ifndef ANIMAL_H
#define ANIMAL_H
#include <iostream>
using namespace std;
class Animal
{
public:
    string name;
    int age;

    Animal();
    void move();
};

#endif // ANIMAL_H
  • cat.cpp
#include "cat.h"

void cat::favorite()
{
    cout << "抓老鼠" << endl;
}

cat::cat()
{

}
  • cat.h
#ifndef CAT_H
#define CAT_H

#include "animal.h"

class cat : public Animal
{
public:
    int jump_heigh;

    void favorite();
    cat();
};

#endif // CAT_H

C++多重继承

#include <iostream>

using namespace std;

//多重继承是一种允许一个类同时继承多个基类的特性,这意味着派生类可以继承多个基类的属性和方法

class A
{
public:
    void displayA()
    {
        cout << "输出A"  << endl;
    }
};


class B
{
public:
    void displayB()
    {
        cout << "输出B"  << endl;
    }
    void displayA()    //不同的基类里面有相同的函数
    {
        cout << "类B中输出A"  << endl;
    }
};

class C : public A , public B   //多重继承
{
public:
    void display();
};
void C :: display()
{
    B :: displayA();
    displayB();
}

int main()
{
    C c;
    c. A :: displayA();
    c.displayB();
    c.display();
    cout << "Hello World!" << endl;
    return 0;
}

C++多态知识

#include <iostream>

using namespace std;

/*
如何实现多态

1、使用纯虚函数:在基类中定义一个虚函数,这个函数可以在任何派生类中直接被重写,使用virtual关键字来声明;
2、创建派生类并重写虚函数:在派生类中,我们提供函数的具体实现,这就像告诉遥控器当你控制这个设备时,这个按钮应该这样工作;
3、通过使用基类类型的指针或引用来调用虚函数时,实际调用的是对象具体实际类型中的函数版本;


为什么要使用多态:
1、灵活性:允许我们编写可以处理不确定类型的对象代码;
2、可扩展性:我们可以添加新的派生类而不必修改基类引用或指针引用;
3、接口与实现分离:我们可以通过设计一个稳定的接口,而将具体的实现留给派生类处理



注意:
派生类中要将基类中声明的所有虚函数全部实现,即使在派生类中的函数体内容为空,也要实现
*/

class Open
{
public:
    string device_name;
    virtual void open_device() = 0; //如果一个虚函数不是纯虚函数,基类需要实现它后,在派生类中重写,在使用多态的时候,如果不在基类中实现就要定义为纯虚函数
//    Open(string a)
//    {
//        device_name = a;
//    }

};

class door : public Open
{
public:
    void open_device() override
    {
        cout << "打开门"  << endl;
    }
//    door(string b) : Open(b)   继承构造函数的时候,会利用积基类的构造函数来初始化基类的成员,同时派生类的构造函数形参名要和继承时写的形参名相同
                                    //例如: : Open(b)而不写 : Open(c)
//    {
//        device_name = b;
//    }
};

class computer : public Open
{
public:
    void open_device() override
    {
        cout << "打电脑"  << endl;    //派生出不同的open,实现多态
    }
};

void test(computer &a)
{
    a.open_device();    //通过引用的方式调用虚函数
}

int main()
{
    Open *device = new computer;   //使用基类的指针来调用虚函数,指针类型是基类的类型,但是new的对象是派生类的类型的指针,指向基类的指针,这就是多态
    device->open_device();
    device->device_name = "电脑";

    //Open C;  抽象类(类中包含至少一个纯虚函数)不能被实例化,因为抽象类不完整,抽象类的目的是为派生类提供一个共同的基础结构



    computer com;

    test(com);
    cout << "Hello World!" << endl;
    return 0;
}

C++接口知识

#include <iostream>

using namespace std;


/*
本质上抽象类和接口是一回事;

一个类作为接口可以通过以下步骤实现:
1、定义抽象类:创建一个纯虚函数的抽象类,这些函数构成了接口的一部分,这些函数在抽象类中只有声明而没有具体的实现
2、派生类是实现接口:派生类继承抽象类,并实现其中的纯虚函数,以具体实现接口定义的方法。

c++中接口也是一种特殊的类,需要满足:
(1) 类中没有定义任何成员变量
(2) 类中所有成员函数都是公有且都是纯虚函数
接口是一种特殊的抽象类,所以抽象类具有只能被继承不能创建对象的特征它也具备。
*/

class leave
{
public:
    virtual void gohome() = 0;
};

class Life
{
public:
    virtual void eat() = 0;
    virtual void sleep() = 0;
    virtual void move() = 0;
};

class Human : public Life,public leave
{
public:
    void eat() override;
    void sleep() override;
    void move() override;
    void gohome() override;   //要将继承的所有虚函数都实现
};
void Human ::eat()
{

}
void Human ::sleep()
{

}
void Human ::move()
{

}
void Human ::gohome()
{

}

int main()
{
    Human people;
    people.eat();
    cout << "Hello World!" << endl;
    return 0;
}

C++中的QList容器类

#include <iostream>

using namespace std;

/*
在QT框架中,QList是一个容器类,他在内部实现类似于一个数组,但也提供了一些链表的特性。QList的设计意在提供一个在多数情况下既高效又方便的通用列表容器。
用于存储元素列表。他提供了丰富的功能,包括添加,删除,访问元素等等。他是一个泛型的容器类。

QList的内部工作原理:
1、数组式存储:大都数情况下使用连续内存存储其元素,可以通过[]访问其元素
2、动态调整大小:与静态数组不同,QList可以动态增长和缩减,自动管理内存分配;
3、链表特性:虽然QList主要基于数组,但它也提供了一些链表的操作,比如在列表的开始或结束处添加或移除元素,这些操作通常比在数组中间插入删除元素更高效;
4、复制时共享内存:QList使用一种称为“隐式共享”或“写时复制”的技术,这意味着,当你复制一个QList时,他不会立即复制所有元素,而是共享相同数据,直到你
尝试修改其中一个列表,此时才进行实际的复制,这使得复制QList变得非常高效。


使用场景:
1、当需要快速访问时(如通过索引访问元素)
2、当主要操作是在列表的两端添加或移除元素


基本用法:
包含头文件:
#include <QList>

创建QList实例:创建一个QList对象,并指定存储的元素类型;
QList <int> list

添加元素:使用append或push_back方法添加元素
list.append(1);

访问元素:使用下标操作符的方式或at()方法访问元素

int first = list[1];
int second = list.at(1);

遍历列表:
//使用迭代器遍历
for(int i=0; i < list.size(); ++i)
{
    qDebug() << list[i];
}

//使用范围基的for循环
for(int item : list)
{
    qDebug()<<item;
}

移除元素:使用removeAt、removeOne、或clear方法移除元素
list.removeAt(1);   //移除索引为1的元素
list.removeOne(3);   //移除一个值为3的元素
list.clear();       //清空整个列表

*/
int main()
{
    cout << "Hello World!" << endl;
    return 0;
}

C++权限知识

#include <iostream>

using namespace std;

//继承:允许一个类(称为派生类或子类)继承另一个类(称为基类或父类)的属性和方法,继承的目的主要是代码重用以及建立一种类型之间的层次关系

/*
特点:
1、代码重用:子类继承父类的属性和方法,减少了代码的重复编写;
2、扩展性:子类可以扩展父类的功能,添加新的属性和方法,或者重写现在的所有方法;
3、多态性:通过继承和虚函数,C++支持多态,允许在运行时调用哪一个函数
*/

/*
基类成员       public继承       protected继承      private继承
public        public          protected         private
protected     protected       proteed           private
private       不可访问          不可访问           不可访问
*/

/*
访问权限        类内部     同一个类对象      派生类(子类)     类外部
public        可访问      可访问           可访问           可访问
private       可访问      不可访问         不可访问          不可访问
protected     可访问      不可访问         可访问            不可访问



*/


class Vehicle
{
public:
    string type;
    string color;

    void run();
protected:
    void run2();
};
void Vehicle :: run2()
{

}

class Car : Vehicle    //继承于Vehicle,继承也分为公有继承,私有继承,保护继承,默认是私有继承
{
public:
    void openDorr();

};

void Car:: openDorr()
{
    type = "Car";   //直接访问父类中的属性
    cout << "在子类中给父类元素赋值" << type <<endl;
}

class bycle : public Vehicle
{
public:
    void go();
};

void bycle :: go()
{
    type = "bycle";
    cout << "在子类中给父类元素赋值" << type <<endl;
}


int main()
{
    Car mycar;
    mycar.openDorr();


    bycle by;
    by.go();

    cout << "Hello World!" << endl;
    return 0;
}

C++模板知识

#include <iostream>

/*
模板是一种通用的编程工具,允许程序员编写泛型代码,使得类或者函数能够适用于多种不同的数据类型而不需要重复编写相似的代码。
C++提供了两种主要类型的模板:类模板和函数模板

类模板:
类模板允许定义通用的类:其中某些类型可以作为参数,这样的类可以处理不同类型的数据,而不需要为每个数据类型编写单独的类;

函数模板:
函数模板允许编写通用的函数,可以处理多种不同类型的数据。

//定义一个通用函数模板
template <typename T>
T add (T a, T b)
{
    return a + b;
}
int main()
{

    //使用通用函数模板调用通用函数
    int result1 = add(5,10);         //函数传参不限定参数类型,只是定义了一个模板
    double result2 = add(3.5,2.7);

}



*/
using namespace std;


template <typename T>   //定义一个通用类模板,T可以表示任何数据类型,类模板不是一个具体的类,不允许在外边实现函数,只能在类内实现函数,而且不能像正常的类那样使用这个类
class PrintEvering     //假如要打印整型和和字符串类型的数据,具体实现流程都是一样的,但是因为参数类型不同所以要创建两个类,分别打印两种数据类型
                       //如果将要打印的参数能够当作形参输入进去,就可以实现一个类打印不同种类的数据了,这时候就要用到T这个类型了,他代表模板。
{
private:
    T data;
public:
    void PrintInfo()
    {
        cout << data <<endl;
    }
    void SetEvering(T data)
    {
        this->data = data;
    }
};

int main()
{
    PrintEvering <int> P;   //不能像原来那样使用类,在定义对象时需要指明定义对象的数据类型,因为是一个模板类,并不知道类内T的数据类型;

    PrintEvering <string> P2;

    P.SetEvering(4);
    P.PrintInfo();

    P2.SetEvering("class template");
    P2.PrintInfo();
    cout << "Hello World!" << endl;
    return 0;
}

C++运算符重载

#include <iostream>

//运算符重载是允许程序员自定义各种运算符(如 + -  == !=等),在自定义类型(类或结构体)上的行为特性
//这意味着你可以定义类似于内置类的运算符行为,使你的定义类型更加直观和易于使用。
/*
基本原则:
1、不可以创建新的运算符:只能重载已经存在运算符;
2、至少有一个操作数是用户定义的类型:不能重载两个基本类型的运算符;
3、不能更改运算符的优先级:重载运算符保持原有的优先级和结合性。

*/
using namespace std;
class Person
{
public:
    string name;
    int age;
    bool operator==(Person temp);  //operator表示运算符重载,bool是该运算符的返回值,temp是运算符的操作对象类型
};

bool Person :: operator==(Person temp)  //外部实现运算符重载
{
    return temp.age == age && temp.name == name;
}

class Point
{
public:
    int x;
    int y;
    Point operator+(Point temp) const;  //+运算符重载,这里的const表明这个operetor+函数不会修改调用它的Point对象

    //Point operator+(const Point &temp) const;  //也可以是引用
};

Point Point :: operator+(Point temp)  const
{
    Point ret;
    ret.x = x + temp.x;
    ret.y = y + temp.y;
    return ret;
}
int main()
{
    //假设姓名和年龄一样的人是同一个人
    Person p1;
    p1.name = "张三";
    p1.age = 20;

    Person p2;
    p2.name = "张三";
    p2.age = 20;

    int ret = p1 == p2;
    cout << ret << endl;


    Point data1;
    Point data2;
    data1.x = 1;
    data1.y = 1;
    data2.x = 2;
    data2.y = 2;

    Point data3 = data1 +data2;

    cout << data3.x << endl;
    cout << data3.y << endl;
    return 0;
}

原文地址:https://blog.csdn.net/FHNCSDN/article/details/143668784

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!