当前位置: 首页> 教育> 锐评 > 西安全网推广公司_ps自学网_软件开发平台_公众号推广平台

西安全网推广公司_ps自学网_软件开发平台_公众号推广平台

时间:2025/8/28 2:27:00来源:https://blog.csdn.net/Mr_vantasy/article/details/144803613 浏览次数:0次
西安全网推广公司_ps自学网_软件开发平台_公众号推广平台

类和对象

  • 0.缺省函数与函数重载
    • 1).缺省函数
    • 2).函数重载
  • 1.类和对象
    • 1).创建一个类
    • 2).类和对象的重点默认成员函数
      • (1).构造函数
        • 1.
        • 2.初始化列表
        • 3.C++11的构造函数直接缺省
      • (2).析构函数
      • (3).拷贝构造函数
      • (4).运算符重载
      • (5).const 成员函数
  • 3.杂项
    • 1).explicit关键字
    • 2).static成员变量和函数
    • 3).友元函数
  • 4.简单的时间类的实现

在学习完C语言后,我们来到了C++,C++是C语言的拓展和延申,C++向下兼容我们的C。
其中C++区别于C语言的最大一个特点之一就是类和对象

0.缺省函数与函数重载

首先我们先对函数重载和缺省函数进行知识储备,类和对象中有许多地方需要用到这几个知识点。

1).缺省函数

缺省参数:是声明或定义函数时为函数的参数指定一个缺省值。在调用该函数时,如果没有指定实参则采用该形参的缺省值,否则使用指定的实参。

就如同一下这种情况:

#include <iostream>
using namespace std;
void test(int a, int b=20, int c=10)
{cout << "a=" << a << " b=" << b << " c=" << c << endl;
}
int main()
{test(1, 2, 3);test(1, 2);test(1);return 0;
}

ps:缺省要从右往左缺省,而不是随机缺省。

2).函数重载

函数重载:是函数的一种特殊情况,C++允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 类型顺序)不同,常用来处理实现功能类似数据类型不同的问题。

就好比

#include <iostream>
using namespace std;
void test(int a, int b=20, int c=10)
{cout << "a=" << a << " b=" << b << " c=" << c << endl;
}
void test(int a, double b)
{cout << "a=" << a << " double=" << b << endl;
}

ps:切不可用几个缺省函数构成函数重载,编译器不能正确识别!!!
那么函数重载的本质是什么呢?为什么C++可以做到而C不能呢?
其实原因就在编译链接的过程之中。
当我们对函数进行编译时,
C语言是直接将函数名编译,而C++却是将函数名处理了之后再进行编译。

1.类和对象

类就好比是一个机器人,你可以让他做任何它可以做的事,但是你不能让他做程序没有设定的事。
类有structclass这两个关键字都可做到定义类

structclass
默认成员变量和函数都是public默认成员变量都是private

public,顾名思义就是对外开放的意思,任何人都可以在外部对其成员进行修改。
private,顾名思义就是不对外开放,故不是任何人都可去进行求改。
实际使用时推荐使用class

1).创建一个类

class stu
{
public:
void changeid(int x)
{_id=x;
}
private:
int _age;
int _id;
}

这就是一个简单的类的创建。
我们可以通过其成员函数对其进行修改,也只能通过这种方式进行。

//如:
class stu
{
public:
void changeid(int x)
{_id=x;
}
private:
int _age;
int _id;
}
int main()
{
stu x;
x.changeid(100);
return 0;
}

2).类和对象的重点默认成员函数

如果不自己定义,编译器会帮我们去自动定义

(1).构造函数

1.

我们创建一个对象的时候需要对其初始化,构造函数就是对其初始化的过程。
具体构造如下:
他的设定就是以自己的名字命名!

class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;};

这里就用到了我们的函数重载。
如果我们不自己去定义的话,编译器默认的构造函数是随机值而且
他会调用我们成员变量中类的构造函数
如下

class test
{public:test(int x){_a=x;{private:int _a;
}
class Date
{int _year;int _day;test;
}
int main()
{Date x;return 0;
}
2.初始化列表

如果我们创建的类里面还有一个类作为成员呢,我们该怎么构造使得代码更加简洁。C++提供了一种全新的方法,叫做初始化列表。

public:A(int a):_a(a),_b(1),_class_test(100,200){}
private
3.C++11的构造函数直接缺省

在C++11的情况下,定义类的成员类型时可以直接缺省。
eg:

class test
{
public:test(){};
private:int _a=10;int _b=100;int _c=100;
}

(2).析构函数

当我们的一个对象的生命周期结束的时候,我们需要回收他们在堆上面的空间,就需要使用我们的析构函数。
析构函数在自己的名字前面加上~就代表了析构函数

class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}~Date(){//free这样的。}private:int _year;int _month;int _day;};

(3).拷贝构造函数

如果我们想让新构造的对象与原来的某个对象相等,我们就可以考虑使用拷贝构造函数。
与构造函数十分类似。
通过

class Date{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}Date(const Date& b){_year=b._year;}~Date(){//free这样的。}private:int _year;int _month;int _day;};

拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
因为你每一次传参都会调用拷贝构造创建临时变量,而创建临时变量又会触发拷贝构造,所以无限递归

编译器默认生成的拷贝构造函数是一种浅拷贝意味着他是一个字节一个字节的进行拷贝,这种浅拷贝在某些情况下并不能实现我们的目的。

(4).运算符重载

1.C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
形同如下:

bool operator<(Date& x)
{return _year<x._year;
}

其实我们发现他与普通的函数非常相似,也就是定义的时候加上operator和运算符罢了
ps .* :: sizeof ? : .这几个是不能进行运算符重载的。
2.编译器默认生成的=运算符其实也是一种浅拷贝。
3.前置++和后置++的运算符重载有所区别

//前置++
Date operator++()
{_year++;return year;
}
//后置++
Date operator++(int)//塞上int完成重载
{Date tmp(*this);_year++;return tmp;
}

我们不难发现后置++的代码运行时间会更长,资源消耗更大。
所以在代码书写的时候,我们尽量要去使用前置++。

(5).const 成员函数

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。
这种形如

void test (int a) const
{_year=a;
}

用const修饰我们的this指针的形式就是const成员函数
eg:

void test (int a) const
{_year=a;
}
//其实与这个一样
void test (const Date* this,int a)
{_year=a;
}

都表示不能对成员进行修改。

3.杂项

1).explicit关键字

这是一个神奇的关键字,它的功能是—可以去除隐式类型转化
什么是隐式类型转化呢?

class Date
{
public:explicit Date(int a=10,int b=10,int c=10){_a=a;_b=b;_c=c;}
private:int _a;int _b;int _c;
};
int main()
{Date a=1;Date b={1,2};Date c={1,2,3};return 0;
}

这上面的这3行对象的初始化其实是有隐式的转化的,
是先创建一个临时的类将1,{1,2},{1,2,3}赋值给我们的临时类,再将临时类拷贝复制到我们的初始化类上。
而explicit就可以不进行这种隐式转化

2).static成员变量和函数

1.static成员是一直存在的,无论你怎么创建都是那一个唯一值。
     1).不能通过构造函数直接初始化,因为他是一个单独开辟的空间(定义类的时候只是一个声明)
     2).在外面初始化之后,不能再通过突破域的方式去访问了,Date::xxx  是不行的。
2.static成员函数是没有this指针的,所以我们可以不用通过对象进行调用,只需突破类域   类::static函数   就可以直接调用。
     1)static成员函数是不能调用非static成员函数的。
     2)static成员函数可以调用static成员的,尽管没有this指针。

3).友元函数

当我们想在对象外面去调用我对象内的private成员变量时,我们就可以使用我们的友元函数

#include <iostream>
using namespace std;
class Date
{
public:friend void f(Date& m);//在这里声明一下Date(int a = 10, int b = 10, int c = 10){_a = a;_b = b;_c = c;}
private:int _a;int _b;int _c;
};
void f(Date& m)
{cout << m._a << endl;
}
int main()
{Date x;f(x);return 0;
}

     为什么要用友元函数呢,如果我们进行<<或者>>操作符重载的时候,直接使用成员函数会导致this指针在ostream之前
     也就会出现cout<<date不行,而date<<cout就能正常输出。
     如果我们一开始就用友元函数进行重载,就可以调整this指针和ostream指针的相对位置。
如下:

#include <iostream>
using namespace std;
class Date
{
public:friend istream& operator>>(istream& in,  Date& x);friend ostream& operator<<(ostream& out, const Date& x);friend void f(Date& m);//在这里声明一下Date(int a = 10, int b = 10, int c = 10){_a = a;_b = b;_c = c;}private:int _a;int _b;int _c;
};
void f(Date& m)
{cout << m._a << endl;
}
ostream& operator<<(ostream& out, const Date& x)
{out << x._a << "-" << x._b << "-" << x._c << endl;return out;
}
istream& operator>>(istream& in,  Date& x)
{in >> x._a >> x._b >> x._c;return in;
}
int main()
{Date x;int tmp = 0;cin >> x >> tmp;cout << tmp << endl;f(x);cout << x << endl;return 0;
}

4.简单的时间类的实现

通过以上的储备,我们已经可以实现一个相对简单的时间类了:

#include <iostream>
using namespace std;class Date
{
public:int Getmonthday(int year,int month){int monthDays[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && year % 4 == 0 && year % 100 != 0){return 29;}return monthDays[month];}bool operator==(const Date&x){return _year == x._year && _month == x._month && _day == x._day;}bool operator<(const Date& x){return _year * 10000 + _month * 100 + _day < x._year * 10000 + x._month * 100 + x._day;}bool operator>(const Date& x){return _year * 10000 + _month * 100 + _day > x._year * 10000 + x._month * 100 + x._day;}bool operator>=(const Date& x){return *this > x || *this == x;}bool operator<=(const Date& x){return *this < x || *this == x;}bool operator!=(const Date& x){return !(*this == x);}Date operator+(int day){int sz = Getmonthday(_year, _month);int count = 0;int total = day + _day;Date tmp(_year, _month, _day);tmp._day = 0;while (total> sz){total-= sz;count++;if (tmp._month + count > 12){tmp._month = 1;count = 0;tmp._year++;}sz = Getmonthday(tmp._year, tmp._month + count);}tmp._day = total;tmp._month += count;return tmp;}Date(int year = 0, int month = 1, int day = 1){if (year >= 0 && month <= 12 && month >= 1 && day >= 1&&day<=Getmonthday(year,month)){_year = year;_month = month;_day = day;}else{cout << "非法数据" << endl;}}Date(const Date& x){_year = x._year;_month = x._month;_day = x._day;}void Print(){cout << "year: " << _year << "\nmonth:" << _month << "\nday:" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{system("chcp 65001");Date test1(2004, 12, 3);Date test2(2001, 11, 3);test1.Print();test1=test1 + 300;test1.Print();if (test1 != test2){printf("你好");}
}

在这里插入图片描述

创作不易,恳请留赞
(*´∀)~♥(*´∀)♥(*´∀`)

关键字:西安全网推广公司_ps自学网_软件开发平台_公众号推广平台

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: