C++ 类与封装不完全指北
来源:互联网 发布:湖首大学知乎 编辑:程序博客网 时间:2024/06/06 09:44
以下内容是个人平时常用的内容,在此进行总结。都是个人的见解,如果有不对或者不赞同的地方,请大家指正,互相学习!
这个学期学习了C++的有关知识,希望能够在这里与大家一起分享。我不想和其他 教科书一样,一步一步一点一点介绍 C++的知识。这样讲了后面忘了前面。在我的学习过程中,我更喜欢那例子说话。所以我通过几个题目和例子来为大家讲解C++类与封装的基本知识。
有关C++的背景啥的我就不在此一一介绍。高手们都说C++不是很好用,因为他的输出具有不确定性等等的原因。但是作为小白倒是觉得C++很多时候用起来比C语言要顺手的多。也许这就是和高手的差距吧。C++是一门面向对象的程序语言,是通过不同的类以及类与类之间的关系来实现不同对象的要求 和特征。因此类是C++中最基础的组成部分。
一.首先来看一下C++中的类与C语言中的结构体
C++中的类与C语言中的结构体十分相似。但是也有不同点。当然,定义时C++是class而C语言是stract,这是最直观的不同。其次,在C语言的结构体中,数据成员和成员函数的默认属性为public,也就是公开,任何结构体外的函数都可以访问到结构体中的成员。而在C++的类中,如果不特别说明,类中的数据成员和成员函数均为protected,也就是处于保护,只有public中的成员函数可以访问并修改protected中的数据成员,其他的函数均不能访问。这样增加了数据成员的安全性。这是二者最显著的区别。
二.通过例子来认识一个简单的类
class Data{//类的定义方式,关键词为classprivate://表示一下的成员为protected类型 int x_;public://表示一下的成员为public类型 Data(int x)//构造函数① { x_ = x; cout<<"Data "<<x_<<" is created."<<endl; } Data() { x_ = 0; cout<<"Data's default constructor."<<endl; } ~Data()//析构函数② { cout<<"Data "<<x_<<" is erased."<<endl; }
void setValue(int a)//如果函数不需要return的话就写为void类型,需要有return的话,需要返回什么类型的数据就讲函数定义为什么类型 { x_ = a; } int getValue() { return x_; } void showValue()//用来输出类的数据成员 { cout<<x_<<endl; }};
①构造函数:构造函数是在创建新的类时调用,可以用来初始化类中的数据成员。
构造函数没有函数类型,因此定义的时候前面不加void,int等等,而且函数名与类名一直。
构造函数是可以重载的,可以满足多种情况下的定义方式。比如:
class Data{protected: int a; int b;public: Data() { a = 0; b = 0; }//当创建类时没有传入参数,调用该构造函数 Data(int aa) { a = aa; b = 0; }//当创建类时传入一个参数,调用该构造函数 Data(int aa,int bb) { a = aa; b = bb; }//当创建类时传入两个参数,调用该函数
};
在main函数中不同的Data定义方式会调用不同的构造函数。比如:
Data data1;//调用Data() Data data2(2);//调用Data(int aa)
Data data3(10,11);//调用Data(int aa,int bb)
构造函数还可以用参数表的方式来写,我们将上面的Data类中的构造函数改写为初始化列表的形式
class Data{protected: int a; int b;public: Data():a(0),b(0) { } Data(int aa):a(aa),b(0) { } Data(int aa,int bb):a(aa),b(bb) { }};
当一个类没有编写构造函数时,编译器在编译的过程中会自动生成构造函数,这个自动生成的构造函数会把所有的数据成员初始化为0.
②析构函数:析构函数是在一个类生命周期结束后,删除这个类时调用的。
构造函数前面不带void,int等任何函数类型,函数名为波浪线+类名,比如Data类的析构函数的函数名为~Data。
一般在类中new出来的空间,需要在析构函数中delete掉。(关于new和delete,请参照其他博文)
如果没有在类中编写析构函数,编译器会自动生成析构函数。
在这里总结一下析构函数的调用时机:1.默认构造函数引用时。 2.返回值类的对象时。 3.用类的对象初始化另一个对象时。 4.函数里的参数是类的对象时。
一个简单的类就是有构造函数,析构函数和其他的函数比如show函数构成的。这样就可以构成一个能实现简单功能的类。但是这样的类并不能实现所有的问题,真正实际应用的类要比这个麻烦的多~~~
三.通过例子来看复杂一些的类
class Time{private: int hour_,minute_,second_; friend class DateTime;public: Time(int h,int m,int s):hour_(h),minute_(m),second_(s) { cout<<"CREATE Time : ("<<hour_<<", "<<minute_<<", "<<second_<<")"<<endl;}//构造函数 Time():hour_ (0),minute_(0),second_(0) {cout<<"CREATE Time : ("<<hour_<<", "<<minute_<<", "<<second_<<")"<<endl; }//无参构造函数 Time(const Time&tt)//拷贝函数① const常量② { hour_ = tt.hour_; minute_ = tt.minute_; second_ = tt.second_; cout<<"COPY Time : ("<<hour_<<", "<<minute_<<", "<<second_<<")"<<endl; } Time& setTime(int hour,int minut,int second)//this指针与引用符&不在本节讲 { hour_ = hour; minute_ = minut; second_ = second; return *this; } void showTime() { cout<<setw(2)<<setfill('0')<<hour_<<":"<<setw(2)<<minute_<<":"<<setw(2)<<second_; }};
①拷贝函数:拷贝函数负责将传入的类中的数据拷贝至现有的类中。
拷贝函数的函数名和类名一致。比如Data类的拷贝函数,函数名为Data。
拷贝函数不能用初始化列表的形式来写。
需要注意,拷贝函数以成员按位复制(bit-by-bit)的方式实现成员的复制,按位复制就是把一个对象个数据成员的值原样复制到目标对象中。在没有涉及指针类型的数据成员时,默认复制构造函数能够很好的工作。但当一个类有指针类型的数据成员时,默认拷贝构造函数会造成指针悬挂问题。所以如果类具有指针类型的数据成员,就该为他提供拷贝构造函数。而不是用默认的拷贝构造函数。
②const常量:详情请看本博客文章《C++中const常量用法总结》
三.通过例子来理解静态成员
using namespace std;class Student{private: int num; int id; int *a; static int s;//静态成员 string name;public: Student(string name_,int *a_,int num_):name(name_),num(num_) { s++; id = s; a = new int[num]; for(int i = 0;i < num;i++) { a[i] = a_[i]; } cout<<"A student whose name is \""<<name<<"\" and id is "<<id<<" is created!"<<endl; } ~Student() { cout<<"A student whose name is \""<<name<<"\" and id is "<<id<<" is erased!"<<endl; delete[]a;//new出来的变量一定要在析构函数中delete掉,否则会造成内存泄漏。 } void showStudent() { cout<<"This student is \""<<name<<"\" whose id is "<<id<<"."<<endl;; cout<<"This student's scores are:"; for(int i=0;i<num;i++) { cout<<" "<<a[i]; } cout<<endl; }};int Student::s = 0;//静态成员的初始化
静态成员。顾名思义,就是不变的静态量。其关键词为static,静态常量定义方式为 static type a ,type为数据类型,a为变量名,在函数前加上static表示将函数定义为静态成员。静态常量只能通过静态函数来读取。并且要在所在类的类外,紧跟着进行初始化。初始化为0或者其他的数。静态成员同样遵循public,private和protected访问限定的限定规则。
静态成员函数是属于整个类的,它只能访问属于该类的静态成员(包括静态数据成员和静态成员函数),不能访问非静态成员(包括非静态数据成员和成员函数)。
静态数据成员时属于整个类的,整个类只有一份拷贝,相当于类的全局变量,供该类所有对象共用,能够被该类的所有对象访问;非静态数据成员的是属于对象的,每个对象都有非静态数据成员的一份拷贝。为该对象所用。
下面通过一个例子来理解静态数据成员的特点:
#include <iostream>using namespace std;class Data{private: static int sum; int a;public: Data(int aa):a(aa) { sum++; } static int getsum() { return sum; }};int Data::sum = 0;int main(){ Data data1(10); Data data2(11);}
四.通过例子理解this指针
首先了解一下this指针的概念。this指针是用于标识一个对象自引用的阴式指针,代表对象自身的地址。由于this指针是在不知晓的情况下,由编译器添加到成员函数参数表中的隐含参数。所以它也称为隐式指针。说明:1.尽管this指针是一个隐式指针,但在类的成员函数中可以显式地使用它 。 2.在类X的非const成员函数里,this的类型就是X*。然而this并不是一个常规变量,不能给他赋值,但可以通过他修改数据成员的值。在类X的const成员函数里,this被设置成const X*类型,不能通过它修改对象的数据成员值。 3.静态成员函数没有this指针,因此静态成员函数中不可以访问对象的非静态成员函数。
通过this返回对象地址或自引用的成员函数,通过例子来说明。
class Date{private: int year_,month_,day_; friend class DateTime;public: Date(int y,int m,int d):year_(y),month_(m),day_(d) { cout<<"CREATE Date : ("<<year_<<", " <<month_<<", "<<day_<<")"<<endl;} Date():year_(1),month_(1),day_(1) { cout<<"CREATE Date : ("<<year_<<", " <<month_<<", "<<day_<<")"<<endl; } Date& setDate(int year,int month,int day) { year_ = year; month_ = month; day_ = day; return *this;//this指针的调用,返回的是传入的Data类,不会创建新的Data类 } Date(const Date& dd) { year_ = dd.year_; month_ = dd.month_; day_ = dd.day_; cout<<"COPY Date : ("<<year_<<", "<<month_<<", "<<day_<<")"<<endl; } void showDate() { cout<<setw(4)<<setfill('0')<<year_<<"-"<<setw(2)<<setfill('0')<<month_<<"-"<<setw(2)<<day_; }};
以上就是对于类与封装方面的总结,希望能够给大家提供帮助。也欢迎大家积极留言,相互学习~~
- C++ 类与封装不完全指北
- C语言不完全类型与延迟定义
- Objective-c 对象与类 封装
- C语言封装线程与日志类
- MySql insert插入操作不完全指北
- vue踩坑不完全指北(1)
- vue踩坑不完全指北(2)
- vue踩坑不完全指北(3)
- react踩坑不完全指北(1)
- react踩坑不完全指北(2)
- react踩坑不完全指北(3)
- react踩坑不完全指北(4)
- [C#]DataGridView封装类
- C 资源之不完全导引
- C语言tips不完全汇总
- JavaScript类与封装
- 类与封装
- GTK+与MFC不完全对比GTK+与MFC不完全对比
- [JLOI2768]冠军调查 BZOJ2768-最小割
- Git使用详细教程(超详细)
- leetcode-13-罗马数字转阿拉伯数字
- Linux中文件存取过程详解
- java简单编译程序的运行
- C++ 类与封装不完全指北
- ROS探索
- 2017.05.06【NOIP提高组】模拟赛B组
- 小小加密应用
- caffe windows10 ssd配置
- 第十一届东北地区大学生程序设计竞赛赛后感想
- JavaScript的onclick函数
- 剑指offer 9. 斐波那契数列
- ftp与tftp比较