• C++杂记


    • 操作符重载:

    情景1,通常情况下,我们将2个数据类型为结构体类型的2个数相加时,所书写的函数。

    代码1:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    #include <iostream>
    using namespace std;
    struct Complex
    {
    float real;
    float image;
    };
    Complex add(Complex a,Complex b)
    {
    Complex c;
    c.image = a.image + b.image;
    c.real = a.real + b.real;
    return c;
    }
    int main()
    {
    Complex aa,bb,cc;
    aa = {1,1};
    bb = {2,2};
    cc = add(aa,bb);
    cout<<"cc.image = "<<cc.image<<endl;
    cout<<"cc.real = "<<cc.real<<endl;
    return 0;
    }

    运行结果:

    1
    2
    cc.image = 3
    cc.real = 3

    情景2,我们可以通过使用操作符重载技术,来实现,像这种结构体类型的数据,可以按照普通的数据类型(char,int ,double……)进行操作。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    #include <iostream>
    using namespace std;
    struct Complex
    {
    float real;
    float image;
    };
    Complex operator+(Complex a,Complex b)
    {
    Complex c;
    c.real = a.real + b.real;
    c.image = a.image + b.image;

    return c;
    }
    int main()
    {
    Complex aa,bb,cc;
    aa = {1,1};
    bb = {2,2};
    cc = aa+bb;
    cout<<"cc.real = "<<cc.real<<endl;
    cout<<"cc.image = "<<cc.image<<endl;
    return 0;
    }

    运行结果:

    1
    2
    cc.real = 3
    cc.image = 3
    • 功能:设置一个简易的电子时钟,可以显示时分秒
    • 技巧:setfill函数,在给定的输出域宽内填充字符; setw函数,设置域宽为n个字符

    源码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    #include <iostream>
    #include <iomanip>
    #include <windows.h>
    #include <unistd.h>
    using namespace std;

    int main()
    {
    int hour = 0,min = 0,sec = 0;
    while(1)
    {
    sec++;
    sleep(1);
    if(sec>=60)
    {
    sec = 0;
    min++;
    if(min>=60)
    {
    min = 0;
    hour++;
    if(hour >= 24)
    {
    hour = 0;
    }
    }
    }
    cout<<setfill('0')<<setw(2)<<hour<<":"<<setw(2)<<min<<":"<<setw(2)<<sec<<endl;
    }
    return 0;
    }

    总结:

    setfill函数和setw函数,这2个函数结合起来使用,用来制作一个简易的电子时钟还是蛮不错的。

    • 函数重载:

    代码1:

    特征:函数重载反映在,函数的返回值和函数的返回参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #include <iostream>
    using namespace std;
    float abs(float f);
    int abs(int i);
    int main()
    {

    float ret_f = abs(-5.5f);
    cout<<ret_f<<endl;

    int ret_i = abs(-5);
    cout<<ret_i<<endl;
    return 0;
    }

    float abs(float f)
    {
    return ((f>0)?(f):(-f));
    }
    int abs(int i)
    {
    return ((i>0)?(i):(-i));
    }

    运行结果:

    1
    2
    3
    5.5

    5

    代码2:

    特征:函数重载反映在,函数的参数。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <iostream>

    using namespace std;
    void abs(int i);
    void abs(double d);
    int main()
    {
    abs((double)4);
    return 0;
    }
    void abs(int i)
    {
    cout<<"int abs(i)"<<endl;
    }
    void abs(double d)
    {
    cout<<"double abs(d)"<<endl;
    }

    运行结果:

    1
    double abs(d)
    • 默认参数:

      代码实战1,

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <iostream>
    #include <time.h>
    using namespace std;
    int volume(int l,int w,int h=6)
    {
    return l*w*h;
    }
    void weatherCast(string w = "pm 2.5")
    {
    time_t t = time(0);
    char tmp[64];
    strftime(tmp,sizeof(tmp),"%Y-%m-%d %X %An",localtime(&t));
    cout<<tmp<<"today's weather "<<w<<endl;
    }
    int main()
    {
    cout<<"volume = "<<volume(1,1)<<endl;
    weatherCast("pm = 555");
    return 0;
    }

    运行结果:

    1
    2
    3
    volume = 6
    2018-11-08 16:36:18 Thursday
    today's weather pm = 555

    总结:

    默认参数,当我们不给它任何的参数时,它就按照形参中实现指定的值。

    当,我们想要设定特定的参数时,那就直接给它传入相应的值即可。

    代码实战2,

    默认参数的存在,的确在一定程度上给我们提供了不少的便利性。然而,它也有它的囧态。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
    using namespace std;
    int abs(int a)
    {
    cout<<"int abs(int a)"<<endl;
    }
    int abs(int a,int b=5)
    {
    cout<<"int abs(int a,int b=5)"<<endl;
    }
    int main()
    {
    abs(1,5);//假如写成:abs(1),此时报错。
    return 0;
    }

    总结,

    ​ 当我们写为abs(1),里面仅有一个参数时,函数会陷入两难的境地,它不知道要执行abs(int a)还是要执行

    abs(int a,int b=5)。

    • 引用:

    引用的定义:引用的意义,是为了给一个已有的变量名起一个别名。

    代码实战1

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
    using namespace std;
    int main()
    {
    int a;
    int &b = a;
    int *p;
    int *&pp = p;

    cout<<"&a = "<<&a<<endl;
    cout<<"&b = "<<&b<<endl;
    cout<<"p = "<<p<<endl;
    cout<<"pp = "<<pp<<endl;
    return 0;
    }

    运行结果:

    1
    2
    3
    4
    &a = 0x28fea4
    &b = 0x28fea4
    p = 0x68
    pp = 0x68
    • 在C语言中,打印一个数字。分别使用十进制、十六进制、八进制的形式打印。

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    #include <stdio.h>
    int main()
    {

    int a = 128;
    printf("dec: a = %dn",a);
    printf("hex: a = %xn",a);
    printf("oct: a = %on",a);
    return 0;
    }

    运行结果:

    1
    2
    3
    dec: a = 128
    hex: a = 80
    oct: a = 200

    在C++中,打印一个数字。分别使用十进制、十六进制、八进制的形式打印。

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #include <iostream>
    #include <stdlib.h>
    #include <iomanip>
    using namespace std;

    int main()
    {
    int a = 1234;
    cout<<dec<<a<<endl;
    cout<<setbase(10)<<a<<endl;
    cout<<"0x"<<hex<<a<<endl;
    cout<<"0x"<<setbase(16)<<a<<endl;
    cout<<oct<<a<<endl;
    cout<<setbase(8)<<a<<endl;
    }

    运行结果:

    1
    2
    3
    4
    5
    6
    1234
    1234
    0x4d2
    0x4d2
    2322
    2322

    总结,dec等价于setbase(10);hex等价于setbase(16);oct等价于setbase(8)。

    • const关键字与引用之间的暧昧。
    1
    2
    3
    4
    5
    6
    7
    8
    情景1:
    const int a = 1234;
    int &b = a;
    该使用方法是错误的。
    情景2:
    int a = 1234;
    const int &b = a;
    该使用方法是OK,正确的。
    • 熟悉new和delete的使用。

    情景1:

    1
    2
    3
    4
    int *p = new int(123);
    cout<<*p<<endl;
    运行结果:
    123

    情景2:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    char *p = new char [10];
    strcpy(p,"hello world");
    cout<<p<<endl;
    运行结果:
    hello world

    string *str = new string("china");
    cout<<str<<endl;
    cout<<*str<<endl;
    运行结果:
    0x3c1518
    china
    • C++中4种强制类型转化。

      tatic_cast reinterpret_cast const_cast dynamic_cast,其中dynamic_cast在后面学习的多态中,会详细来讲今天,暂且不提。

    static_cast

    它用来解决全双隐问题和半双隐问题。

    全双隐问题(a.b两种数据类型的变量,a既可以赋值给b,b又可以赋值给a)

    半双隐问题(a,b两种类型的变量,a可以赋值给b,b不可以赋值给a;或者…..)

    下面先看一下static_cast使用在什么地方呢?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    1. 全双隐问题:
    int a;
    float b;
    a = b;
    b = a; 首先,上面这4行代码是正确的。在这种情形之下,恰好也就是static_cast的用武之地了。
    如下,
    int a = 123;
    float b = 1.23;
    a = static_cast<float>(b);
    b = static_cast<int>(a);
    cout<<a<<"t"<<b<<endl;
    运行结果:
    1 1

    2. 半双隐问题:
    int *p;
    void *q;
    q = p;//这样写是正确的。但是,p = q,这样写的话,就是错误的。
    p = static_cast<int *>(q); // 这样写也是正确的。

    reinterpret_cast

    它是用来解决,2个方向都是不可以转换的。

    1
    2
    3
    4
    5
    6
    7
    char *p;
    int *q;
    此时,无论是p = q;还是q = p都是不正确的。
    然而,
    p = reinterpret_cast<char *>(q);
    q = reinterpret_cast<int *>(p);
    这2种情况都是正确的。

    const_cast

    它是用来脱常的。(正常情况下,引用是只可以对变量进行取引用的。但是,有了const的介入,就导致了引用,它不止可以对变量取引用。而且它还可以对常量或者表达式取引用。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    情景1,
    谈一谈const的妙用之处。通常情况下,引用只可以对一个变量,进行取引用操作。而,自从有了const关键字之后,它,所实现的功能:取引用,即可以对常量取引用;也可以对表达式进行取引用操作。
    void func_1(int &a)
    {

    }
    main:
    int a = 3;
    func_1(a);
    以上代码是完全没有毛病的。这也是引用的一般、正常的使用方法。
    void func_2(const int &a)
    {

    }
    main:
    int a = 3;
    func_1(3);
    func_1(a+3); //这2个调用,在没使用const之前都是行不通的。但是,在这里都是OK的。
    情景2,
    正式来讲一下const_cast是如何使用的。
    void func(int &a)
    {

    }
    main:
    const int a = 3;
    func(a); //此时,这样调用函数,一定是错误的。
    func(const_cast<int &>(a)); //把原本为const类型的变量,给,成功的"脱常"。
    情景3,
    const int a = 12;
    int &ra = a; //此时,编译报错。
    使用const_cast即可解决上述问题。
    int &ra = const_cast<int &>(a);
    情景4,
    const int a = 10;
    int *p = const_cast<int *>(&a);
    *p = 30;
    cout<<"*p = "<<*p<<"t"<<"a = "<<a<<endl;
    注意:
    const_cast一般只用于引用和指针,是不可以用于变量的。具体,const_cast<int &> const_cast<int *>...
    • C++中命名空间的引入。

    定义:命名空间是对全局区域的再次划分。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    情景1,
    int val = 200;
    main:
    int val = 100;
    cout<<"::val = "<<::val<<endl;
    cout<<"val = "<<val<<endl;
    运行结果:
    ::val = 200
    val = 100
    情景2,
    namespace my_space
    {
    int x=5,y=5;
    namespace others
    {
    int m = 6,n = 6;
    }
    }
    main:
    using namespace my_space::others;
    cout<<"m = "<<m<<"t"<<"n = "<<n<<endl;
    运行结果:
    m = 6 n = 6

    类与对象:

    • 构造器、析构器、使用初始化列表来初始化参数。

    构造器:在类对象创建时,自动调用。

    析造器:在对象销毁时,自动调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    class Line
    {
    public:
    void setLength(double len);
    double getLength(void);
    Line();
    ~Line();
    private:
    double length;
    };
    //构造器
    Line::Line(void)
    {
    cout<<"Object is being created"<<endl;
    }
    //析造器
    Line::~Line(void)
    {
    cout<<"Object is being deleted"<<endl;
    }
    void Line::setLength(double len)
    {
    length = len;
    }
    double Line::getLength()
    {
    return length;
    }
    main:
    Line line;
    line.setLength(6.66);
    cout<<"length of line :"<<line.getLength()<<endl;
    运行结果:
    Object is being created
    length of line :6.66
    Object is being deleted

    使用初始化列表来初始化参数。

    ​ 注意它使用的场景,适用于构造器身上。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    情景1,
    class Line
    {
    public:
    void setLength(double len);
    double getLength(void);
    Line(double len);
    ~Line();
    private:
    double length;
    };
    //使用初始化列表,来初始化参数。
    Line::Line(double len)
    :length(len)
    {
    cout<<"Object is being created,length = "<<len<<endl;
    }
    Line::~Line(void)
    {
    cout<<"Object is being deleted"<<endl;
    }
    main:
    Line line(1.23); //注意这里的对象,在初始化时,方式和前面是不一样的。
    运行结果:
    Object is being created,length = 1.23
    Object is being deleted
    情景2,
    class A
    {
    public:
    A(char *ps)
    :len(strlen(name.c_str())),name(ps){} //c_str()将string类型转化为char *类型的
    void dis()
    {
    cout<<len<<endl;
    }
    private:
    string name;
    int len;
    };
    main:
    A a("a");
    a.dis();
    注意:
    使用初始化列表初始化参数时,一定要注意,初始化的先后顺序。
    • 拷贝构造:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34< 大专栏  C++杂记/span>
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    拷贝构造的格式:
    class 类名
    {
    类名(const 类名 &another)
    拷贝构造体
    }
    情景1,浅拷贝。(默认的)
    class A
    {
    public:
    A(int d,char *p)
    :data(d)
    {
    pd = new char[strlen(p)+1];
    strcpy(pd,p);
    }
    ~A()
    {
    delete []pd;
    }
    #if 0
    // 这是深拷贝时,自己手动创建的拷贝构造器。
    A(const A &another)
    {
    pd = new char[strlen(another.pd)+1];
    strcpy(pd,another.pd);
    }
    #endif
    void dis()
    {
    cout<<data<<"t"<<pd<<endl;
    }
    private:
    int data;
    char *pd;
    };
    main:
    A a(1,"a");
    a.dis();
    A b(a);
    b.dis();
    运行结果:
    1 a
    1 a
    情景2,深拷贝。(需要自己提供)
    见情景1,中的代码。加上,"#if 0...#endif"自己手动添加的拷贝构造器,之后,运行结果如下。
    1 a
    104 a
    情景3,深拷贝。
    class A
    {
    public:
    A(int d,char *p)
    :data(d)
    {
    pd = new char[strlen(p)+1];
    strcpy(pd,p);
    }
    ~A()
    {
    delete []pd;
    }
    A(const A& another)
    {
    pd = new char[strlen(another.pd)+1];
    strcpy(pd,another.pd);
    }
    void dis()
    {
    cout<<data<<"t"<<pd<<endl;
    }
    private:
    int data;
    char *pd;
    };
    main:
    A a(123,"abc");
    A b = a;
    a.dis();
    b.dis();
    运行结果:
    123 abc
    104 abc
    • this指针。

    定义:系统在创建对象时,默认生成指向当前对象的指针。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    class Stu
    {
    public:
    Stu(string name,int age)
    {
    this->name = name;
    this->age = age;
    }
    Stu &growUp()
    {
    this->age++;
    return *this;
    }
    void display()
    {
    cout<<name<<"--"<<age<<endl;
    }
    private:
    string name;
    int age;
    };
    main:
    Stu s("lbc",25);
    s.display();
    s.growUp();
    s.display();
    运行结果:
    lbc--25
    lbc--26
    • 构造器、拷贝构造、赋值运算符重载,这3者放一块,做一个比较。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    class my_str
    {
    public:
    my_str(){}
    //构造器,带参数的
    my_str(int _id,char *_name)
    {
    cout<<"constructor"<<endl;
    id = _id;
    name = new char[strlen(_name)+1];
    strcpy(name,_name);
    }
    //拷贝构造
    my_str(const my_str &str)
    {
    cout<<"copy constructor"<<endl;
    id = _id;
    name = new char[strlen(str.name)+1];
    strcpy(name,str.name);
    }
    //赋值运算符重载
    my_str &operator=(const my_str &str)
    {
    cout<<"operator = "<<endl;
    if(this != &str)
    {
    this->id = str.id;
    int len = strlen(str.name);
    name = new char[len+1];
    strcpy(name,str.name);
    }
    return *this;
    }
    ~my_str()
    {
    delete name;
    }
    private:
    char *name;
    int id;
    };
    main:
    my_str str1(123,"abc");
    cout<<"------------------"<<endl;
    my_str str2;
    str2 = str1; //这里是,赋值运算符重载
    cout<<"------------------"<<endl;
    my_str str3 = str2; //这里是,拷贝构造
    运行结果:
    constructor
    ------------------
    operator =
    ------------------
    copy constructor

    注意: 深拷贝也可以称之为拷贝构造。

    • const关键字构成的函数重载。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class A
    {
    public:
    A():x(12),y(34){}
    void dis()
    {
    cout<<"void dis()"<<endl;
    cout<<x<<"t"<<y<<endl;
    }
    void dis() const
    {
    cout<<"void dis() const"<<endl;
    cout<<x<<"t"<<y<<endl;
    }
    private:
    int x,y;
    };
    main:
    A a;
    a.dis();
    运行结果:
    void dis()
    12 34
    总结:
    const关键字修饰函数时,是可以构成函数重载的。此时,优先执行,非const修饰的函数。
    • static关键字在C++中的用法。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    情景1,
    点1:static修饰的类成员,不需要类对象,也是可以对其成员进行访问的。
    点2:要想使用static类型的成员,必须先要对其初始化。而且,这个初始化的过程还必须在类外,进行初始化
    class School
    {
    public:
    static void add_lib_book(string book)
    {
    lib = lib + book;
    }
    public:
    string tower;
    string lake;
    static string lib;
    };
    string School::lib = "jx lib";
    main:
    School::lib = "jx lib";
    cout<<School::lib<<endl;
    School::add_lib_book(" good book");
    cout<<School::lib<<endl;
    运行结果:
    jx lib
    jx lib good book

    情景2,
    static函数存在的意义在于,用来管理类中的静态成员变量。
    class Student
    {
    public:
    Student(int n,int a,float s)
    :num(n),age(a),score(s){}
    static float average();
    void total()
    {
    count++;
    sum = sum + score;
    }
    private:
    int num;
    int age;
    float score;
    static float sum;
    static int count;
    };

    float Student::sum = 0;
    int Student::count = 0;
    float Student::average()
    {
    return sum/count;
    }
    main:
    Student stu[3] = {
    Student(100,10,1),
    Student(200,20,2),
    Student(300,30,3)
    };
    for(int i=0;i<3;i++)
    {
    stu[i].total();
    cout<<Student::average()<<endl;
    }
    运行结果:
    1
    1.5
    2
    • this指针
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    实战1,this指向普通函数
    void dis(int cnt)
    {
    cout<<"cnt = " <<cnt<<endl;
    }
    main:
    void (*pf)(int) = dis;
    pf(10)
    运行结果:
    cnt = 10
    实战2,this指向类成员函数
    class Student
    {
    public:
    Student(string n,int a)
    :name(n),age(a){}
    void dis()
    {
    cout<<"name: "<<name<<"t"<<"age: "<<age<<endl;
    }
    string name;
    int age;
    };
    main:
    Student s("lbc",120);
    void (Student::*pf)() = Student::dis;//这里要注意,函数指针书写的格式。
    (s.*pf)();
    运行结果:
    name: lbc age: 120
    • 友元函数friend
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    情景1,
    class Point
    {
    public:
    Point(float xx,float yy)
    :x(xx),y(yy){}
    void get_point();
    friend float cal_distance(Point &a,Point &b);
    private:
    float x,y;
    };
    void Point::get_point()
    {
    cout<<"("<<x<<","<<y<<")"<<endl;
    }
    float cal_distance(Point &a,Point &b)
    {
    float d_x = a.x - b.x;
    float d_y = a.y - b.y;
    return sqrt(d_x*d_x - d_y*d_y);
    }
    main:
    Point p1(1.1,2.2);
    Point p2(2.2,2.2);
    p1.get_point();
    p2.get_point();
    float res = cal_distance(p1,p2);
    cout<<"res = "<<res<<endl;
    运行结果:
    (1.1,2.2)
    (2.2,2.2)
    res = 1.1
    情景2,
    class Point;
    class Cal_distance
    {
    public:
    float distance(Point &a,Point &b);
    };
    class Point
    {
    public:
    Point(float xx,float yy)
    :x(xx),y(yy){}
    void get_point();
    friend float Cal_distance::distance(Point &a,Point &b);
    private:
    float x;
    float y;
    };
    void Point::get_point()
    {
    cout<<"("<<x<<","<<y<<")"<<endl;
    }
    float Cal_distance::distance(Point &a,Point &b)
    {
    float d_x = a.x - b.x;
    float d_y = a.y - b.y;
    return sqrt(d_x*d_x + d_y*d_y);
    }
    main:
    Point p1(1.1,2.2);
    Point p2(1.1,3.3);
    p1.get_point();
    p2.get_point();
    Cal_distance cd;
    float res = cd.distance(p1,p2);
    cout<<"res = "<<res<<endl;
    运行结果:
    (1.1,2.2)
    (1.1,3.3)
    res = 1.1
    总结:
    友元函数friend函数,从目前来看它,的不同之处在于,它可以访问private的成员。
    • 运算符重载
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    情景1,成员函数重载
    class Complex
    {
    public:
    Complex(float xx=0,float yy=0)
    :x(xx),y(yy){}
    void dis();
    Complex operator+(const Complex &another);
    private:
    float x,y;
    };
    void Complex::dis()
    {
    cout<<"x="<<x<<"t"<<"y="<<y<<endl;
    }
    Complex Complex::operator+(const Complex &another)
    {
    return Complex(this->x+another.x,this->y+another.y);
    }
    main:
    Complex p1(1.1,2.2);
    Complex p2(1.1,0.0);
    p1.dis();
    p2.dis();
    Complex p3 = p1+p2;
    p3.dis();
    运行结果 :
    x=1.1 y=2.2
    x=1.1 y=0
    x=2.2 y=2.2

    情景2,友元函数重载
    class Complex
    {
    public:
    Complex(float xx=0,float yy=0)
    :x(xx),y(yy){}
    void dis();
    friend Complex operator+(Complex &a,Complex &b);
    private:
    float x,y;
    };
    void Complex::dis()
    {
    cout<<"x="<<x<<"t"<<"y="<<y<<endl;
    }
    Complex operator+(Complex &a,Complex &b)
    {
    return Complex(a.x+b.x,a.y+b.y);
    }
    main:
    Complex p1(1.1,2.2);
    Complex p2(1.1,0.0);
    p1.dis();
    p2.dis();
    Complex p3 = p1+p2;
    p3.dis();
    运行结果:
    x=1.1 y=2.2
    x,1.1 y=0
    x=2.2 y=2.2

    继承Inherit

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    情景1,
    class People
    {
    public:
    void eat(string food)
    {
    cout<<"I am eating : "<<food<<endl;
    }
    };
    class Student :public People
    {
    public:
    void study(string subject)
    {
    cout<<"I am studying : "<<subject<<endl;
    }
    };
    class Teacher :public People
    {
    public:
    void teach(string subject)
    {
    cout<<"I am teaching : "<<subject<<endl;
    }
    };
    main:
    Student s;
    Teacher t;
    s.eat("Student");
    s.study("China");
    cout<<"------------------"<<endl;
    t.eat("Teacher");
    t.teach("English");
    运行结果:
    I am eating : Student
    I am studying : China
    ------------------
    I am eating : Teacher
    I am teaching : English

    情景2,看一下继承与虚继承之间的差异。
    class Base
    {
    public:
    Base(int d = 10)
    :data(d){}
    void dis()
    {
    cout<<"Base data = "<<data<<endl;
    }
    int data;
    };
    class A :virtual public Base
    {
    public:
    A()
    {
    cout<<"A() Base data = "<<data<<endl;
    }
    void set_data(int d)
    {
    data = d;
    }
    };
    class B:virtual public Base
    {
    public:
    B()
    {
    cout<<"B() Base data = "<<data<<endl;
    }
    int get_data()
    {
    return data;
    }
    };
    class C:public A,public B
    {
    public:
    C()
    {
    cout<<"C() Base data = "<<data<<endl;
    }
    void dis()
    {
    cout<<"C() data = "<<data<<endl;
    cout<<"A() data = "<<data<<endl;
    cout<<"B() data = "<<data<<endl;
    }

    };
    main:
    C c;
    c.dis();
    运行结果:
    A() Base data = 10
    B() Base data = 10
    C() Base data = 10
    C() data = 10
    A() data = 10
    B() data = 10
    总结,这里假如没有virtual修饰的话,class C中想要输出data的值是,会出现"data is ambiguous"的这种关键字样。这个data,它,不知道应该从class A,还是从class B中获取的。
  • 相关阅读:
    端口
    log4j常用配置以及日志文件保存位置
    jbpm node signal
    JBPM3.2 TABLE
    JBPM TaskInstance 对象创建过程
    【转】链接脚本
    快速平方根倒数
    GPS开发之知识储备(NMEA0183)
    HEX文件格式和其校验算法
    NRF51822之IIC(MEMS_LIS2DH12)
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12347537.html
Copyright © 2020-2023  润新知