lesson3-C++类和对象(下)(三)

简介: lesson3-C++类和对象(下)(三)

lesson3-C++类和对象(下)(二)+https://developer.aliyun.com/article/1393915

匿名对象

直接看示例:

#include <iostream>
using namespace std;
class A
{
public:
  A()
  {
    _count++;
  }
  A(const A& a)
  {
    _count++;
  }
  static int Get_count()
  {
    return _count;
  }
  class B
  {
  public:
    B()
    {
      _count++;
      _a = 3;
    }
  private:
    int _a;
  };
private:
  int _A;
  static int _count;
};
int A::_count = 0;
int main()
{
  cout << sizeof(A) << endl;
    //匿名对象调用成员函数
  cout << A().Get_count() << endl;
  return 0;
}

匿名对象就是没有名字的对象,生命周期只在本行。语法就是类名加括号表示匿名对象。

拷贝对象时的一些编译器优化

class Date
{
public:
  Date(int year = 2023, int month = 11, int day = 3)
    :_year(year)
    , _month(month)
    , _day(day)
    ,count(0)
  {
    _count++;
    count = _count;
    cout << "构造-" << count << endl;
  }
  Date(const Date& a)
    :count(0)
  {
    _count++;
    count = _count;
    cout << "拷贝构造-" << count << endl;
  }
  ~Date()
  {
    cout << "析构-" << count << endl;
  }
  Date& operator=(const Date& a)
  {
    cout << "赋值" << endl;
    return *this;
  }
private:
  int _year;
  int _month;
  int _day;
  int count;
  static int _count;
};
int Date::_count = 0;
void func(Date aa)
{
}
Date func()
{
  Date a;
  return a;
}

接下来我们来写测试用例:

测试用例一:

int main()
{
  Date a;
  a = 1;
  return 0;
}

首先是a构造,接着临时对象构造,临时对象赋值给a,临时对象生命周期只在本行,临时对象析构,主函数结束a析构。


int main()
{
  //隐式类型转换,首先是1先构造一个临时对象,接着是
  //临时对象拷贝构造a
  Date a = 1;
  return 0;
}

所以这就是编译器的优化,将构造加拷贝构造优化为--->构造,只有在一行上编译器才会优化。

而且只有比较新的编译器才会这么去优化,老版本的编译器是不会优化的。

至于为什么不是赋值而是拷贝构造,是因为一个存在的对象给一个将要创建的对象,是拷贝构造,而一个存在的对象给一个也已经存在的对象才是赋值。



void func(Date aa)
{
}
int main()
{
  Date a;
  func(a);
  return 0;
}


void func(Date aa)
{
}
int main()
{
  //2构造匿名对象,匿名对象拷贝构造aa
  func(Date(2));
  return 0;
}

一行上,构造+拷贝构造优化为--->构造


void func(Date aa)
{
}
int main()
{
  //隐式类型转换,3构造临时对象,临时对象拷贝构造aa
  func(3);
  return 0;
}

同样被优化为只有构造。



测试用例二:

Date func()
{
  Date aa;
  return aa;
}
int main()
{
  Date a;
  a = func();
  return 0;
}

a构造,aa构造,接着返回值拷贝构造临时对象,aa析构,临时对象赋值给a,如果不优化,应该是这样:

  1. 构造-1
  2. 构造-2
  3. 拷贝构造-3
  4. 析构-2
  5. 赋值
  6. 析构-3
  7. 析构-1

Date func()
{
  Date aa;
  return aa;
}
int main()
{
  Date a = func();
  return 0;
}

这个优化更厉害了,构造,拷贝构造+拷贝构造,最后优化到只剩构造。

再次理解封装

我们用洗衣机来举例,就像我们知道洗衣机的一系列属性,将这些属性写到一个类里,这个类就是用来描述洗衣机属性的,但他是洗衣机吗?不是,用这些属性实例化出来的对象才是洗衣机,就像我们现实生活中尽管我们清楚洗衣机的属性,但是不买一个也没有办法去洗衣服。

练习题

求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)

class Sum
{
public:
    Sum()
    {
        _i++;
        _sum += _i;   
    }
    static int Get_sum()
    {
        return _sum;
    }
private:
    static int _i;
    static int _sum;
};
int Sum::_i = 0;
int Sum::_sum = 0;
class Solution 
{
public:
    int Sum_Solution(int n) 
    {
        Sum arr[n];
        return Sum::Get_sum();
    }
};

日期差值_牛客题霸_牛客网 (nowcoder.com)

#include <iostream>
using namespace std;
class Sub
{
public:
    Sub(int date)
        :_date(date)
    {}
    int GetMonth(int year,int month) const;
    int operator-(Sub& d);
private:
    int _date;
    int _year;
    int _month;
    int _day;
};
int main()
{
    int Date1,Date2;
    cin >> Date1 >> Date2;
    int temp;
    if(Date1 > Date2)
    {
        temp = Date1;
        Date1 = Date2;
        Date2 = temp;
    }
    Sub d1(Date1);
    Sub d2(Date2);
    cout << (d1-d2) << endl;
    return 0; 
}
// 64 位输出请用 printf("%lld")
int Sub::operator-(Sub& d)
{
    _year = _date/10000;
    _month = _date/100%100;
    _day = _date%100;
    d._year = d._date/10000;
    d._month = d._date/100%100;
    d._day = d._date%100;
    int month = 1;
    int day = 1;
    int total = 0;
    if(_year == d._year)
    {
        if(_month == d._month)
        {
            return abs(_day-d._day+1);
        }
        else 
        {
            int month = 1;
            int total_1 = 0;
            while(month < _month)
            {
                total_1 += GetMonth(_year,month);
            }
            total_1 += _day;
            month = 1;
            int total_2 = 0;
            while(month < d._month) 
            {
                total_2 += GetMonth(_year,d._month);
            }
            total_2 += d._day;
            return abs(total_1 - total_2 + 1);
        }
    }
    else 
    {
        int month = 1;
        int total_1 = 0;
        while(month < _month)
        {
            total_1 += GetMonth(_year,month);
            month++;
        }
        total_1 += _day;
        total_1 = 365 - total_1;
        if(_month>2 && _year%4==0 && _year%100!=0 || _year%400==0)
        {
            total_1--;
        }
        month = 1;
        int total_2 = 0;
        while(month < d._month) 
        {
            total_2 += GetMonth(_year,month);
            month++;
        }
        total_2 += d._day;
        total = total_1 + total_2;
        if(d._year - _year > 1)
        {
            for(int i=_year+1; i<d._year; i++)
            {
                if(_year%4==0 && _year%100!=0 || _year%400==0)
                {
                    total++;
                }
            }
            total += 365 * (d._year-1);
        }
    }
    return total + 1;
}
int Sub::GetMonth(int year,int month) const
{
    int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    if(month == 2 && (_year%4==0 && _year%100!=0 || _year%400==0))
    {
        return 29;
    }
    return month_day[month];
}

打印日期_牛客题霸_牛客网 (nowcoder.com)

#include <iostream>
using namespace std;
int main() 
{
    int year;
    int n;
    int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    while(scanf("%d %d",&year,&n) != EOF)
    {
        int month = 1;
        int day = 1;
        while(n > month_day[month])
        {
            n -= month_day[month];
            month++;
        }
        if(month > 2 && (year%4 ==0 && year%100 != 0 || year%400 == 0))
        {
            n--;
            if(n == 0)
            {
                month--;
                n = 29;
            }
        }
        day = n;
        printf("%d-%02d-%02d\n",year,month,day);
    }
}
// 64 位输出请用 printf("%lld")

日期累加_牛客题霸_牛客网 (nowcoder.com)

#include <iostream>
using namespace std;
int main() 
{
    int n;
    cin >> n;
    int year,month,day,Add_Day;
    int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31};
    while(n--)
    {
        cin >> year >> month >> day >> Add_Day;
        int count = 0;
        while(count < Add_Day)
        {
            count++;
            day++;
            int num = month_day[month];
            if(month == 2 && (year%4 == 0 && year%100 != 0 || year % 400 == 0))
            {
                num++;
            }
            if(day > num)
            {
                day = 1;
                month++;
            }
            if(month == 13)
            {
                month = 1;
                year++;
            }
        }
        printf("%d-%02d-%02d\n",year,month,day);
    }
}
// 64 位输出请用 printf("%lld")


目录
相关文章
|
11天前
|
C语言 C++
从C语言到C++⑧(第二章_类和对象_下篇_续)笔试选择题和OJ题
从C语言到C++⑧(第二章_类和对象_下篇_续)笔试选择题和OJ题
16 0
|
11天前
|
Java 编译器 C语言
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象(下)
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象
9 0
|
11天前
|
C语言 C++
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象(中)
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象
22 0
|
11天前
|
编译器 C语言 C++
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象(上)
从C语言到C++⑦(第二章_类和对象_下篇)初始化列表+explicit+static成员+友元+内部类+匿名对象
12 1
|
11天前
|
编译器 C语言 C++
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(下)
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题
23 2
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(下)
|
11天前
|
编译器 C语言 C++
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(中)
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题
21 1
|
11天前
|
算法 编译器 C语言
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题(上)
从C语言到C++⑥(第二章_类和对象_中篇_续)大练习(日期类)+笔试选择题
22 3
|
11天前
|
编译器 C语言 C++
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)(下)
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)
7 1
|
11天前
|
编译器 C语言 C++
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)(中)
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)
11 0
|
11天前
|
编译器 C语言 C++
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)(上)
从C语言到C++⑤(第二章_类和对象_中篇)(6个默认成员函数+运算符重载+const成员)
9 0