zoukankan      html  css  js  c++  java
  • 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中获取的。
  • 相关阅读:
    剑指Offer-30.连续子数组的最大和(C++/Java)
    剑指Offer-29.最小的K个数(C++/Java)
    UVA 1616 Caravan Robbers 商队抢劫者(二分)
    UVA 10570 Meeting with Aliens 外星人聚会
    UVA 11093 Just Finish it up 环形跑道 (贪心)
    UVA 12673 Erratic Expansion 奇怪的气球膨胀 (递推)
    UVA 10954 Add All 全部相加 (Huffman编码)
    UVA 714 Copying Books 抄书 (二分)
    UVALive 3523 Knights of the Round Table 圆桌骑士 (无向图点双连通分量)
    codeforecs Gym 100286B Blind Walk
  • 原文地址:https://www.cnblogs.com/lijianming180/p/12347537.html
Copyright © 2011-2022 走看看