C++学习笔记 类和对象(一)

类和对象(一)

1. 类的构成

  • 类名
  • 数据成员
  • 成员函数

2. 类成员的三种访问属性

访问属性属性名使用范围
公有类型public可以由程序中的函数访问
保护类型protected可以由本类和本类的派生类访问
私有类型private只能由本类的成员函数访问
  • 默认情况下,类体中没有访问关键词时,类中的成员默认为私有的
  • 数据成员可以是任意数据类型,但是不可以是自动类型
  • 不能在类的声明当中给数据成员赋初值
private:
   int year = 2018;//错误,不可以在声明中进行赋值;
  • struct和class声明的类的区别
    • 默认访问属性不同: 前者默认是public,后者默认是private
    • 类更好的体现了面向程序设计中封装与信息隐藏的特点

3. 类的成员函数

成员函数的定义方式
  1. 将成员函数直接定义在类体中
public:
   void method1(){
      cout<<"在类体中直接定义成员函数";
      }
  1. 在类定义中给出成员函数的原型,函数体写在类的定义之外
    返回值类型 函数名(参数列表);
    返回值类型 类名:: 函数名(参数列表){}
class study
{
     public: 
        void method2(int,int);//函数原型
};
void study::method2(int a, int b)//函数的实现
{
       x = a;
       y = b;
}
       
  1. 显示声明函数的内联函数
  • inline 返回类型 类名 :: 成员函数名(参数表){函数体}
  • 使用inline说明内联函数时,必须使用函数体和inline说明结合在一起,否则编译器将它作为普通函数处理

4. 对象的定义

  • 在声明的同时直接定义对象
class point{
}op1,op2;
  • 声明了类之后在使用时定义对象
point op1,op2;//类名 对象名;

5. 对象中成员的访问

  • 圆点访问形式: 对象名.成员名 || (*指向对象的指针).成员名
  • 指针访问形式: 对象指针变量名 -> 成员名 || (&对象名)->成员名
class calendar{
   int day;
   int month;
   int year;
};
int main(){
   calender c1;
   calender *c2 = new calender;
   //圆点访问形式
   cout << c1.year << endl;
   cout << (*c2).year << endl;
   //指针访问形式
   cout << c2->year << endl;
   cout << (&c2)->year << endl;
   }

6. 构造函数

  • 构造函数是与类名同名的特殊的成员函数,当定义该类的函数时,构造函数被系统自动调用,以实现对对象的初始化.
  • 构造函数必须和类名同名,以类名为函数名的函数一定是类的构造函数
  • 构造函数没有返回值类型,但是有隐含的返回值,该值由系统内部使用
  • 可以有不同类型的参数
  • 构造函数是特殊的成员函数,函数体可以写在类体内,也可以写在类体外
  • 构造函数可以重载,一个类中可以定义多个参数个数或者参数类型不同的构造函数
  • 构造函数被声明为公有函数,但他不能显示调用,他在定义对象的同时被系统自动调用
    [对比理解: 说白了C++的构造函数综合了java中的无参和有参构造函数,通过重载实现了各种形式的有参构造函数]
  • 构造函数的作用说白了就是实现数据成员的初始化

7. 析构函数

  • 析构函数也是一种特殊的成员函数,和构造函数的作用相反,通常用于撤销一些清理任务,比如释放分配给对象的内存空间
  • 析构函数的名称: ~类名
  • 析构函数没有返回类型和参数,不能够随意调用,没有重载,也是由系统自动调用
  • 一般系统会自动创建一个析构函数,但是如果对象中由动态分配的内存时,需要显示的为该类提供适当的析构函数,以完成清理工作
  • 一个中只能有一个析构函数
  • 对象被析构的顺序和建立时的顺序相反,最后被构造的对象最先被析构
  • 调用析构函数的情况:
    • 当一个对象被定义在一个函数体内时,在这个函数体结束的时候对象的析构函数会被自动调用
    • 当一个对象使用new运算符动态创建,在使用delete运算符释放它时,delete会自动调用析构函数

8. 重载构造函数

  • 参数个数或者类型不同实现重载

9. 拷贝构造函数

  • 拷贝构造函数也是类的一个重载版本的构造函数,是一种特殊的构造函数,其形参是对本类对象的引用
  • 拷贝构造函数的功能是用于实现对象值的拷贝.通过将一个同类对象的值拷贝给一个新对象而完成新对象的初始化,即用一个对对象去构造另外一个对象
  • 拷贝构造函数的特点:
  1. 函数只有一个参数,并且是同类对象的引用
  2. 每一个类都必须有一个拷贝构造函数,一般情况下,系统会自动生成一个默认的拷贝构造函数
  • 拷贝构造函数被系统自动调用的情况
  1. 由一个对象初始化另外一个对象时
  2. 当对象作为函数的实际参数传递给函数的值形式参数时
  3. 当对象作为函数返回值时

综合使用

析构函数的辨析

源代码

#include <iostream>

using namespace std;

class A
{
public:
    A()
    {
        cout << "constructing A" << endl;
    }
    ~A()
    {
        cout << "destructing A" << endl;
    }
private:
    int a;
};

class C
{
public:
    C()
    {
        cout << "constructing C" << endl;
    }
    ~C()
    {
        cout << "destructing C" << endl;
    }
private:
    int c;
};

class B : public A
{
public:
    B()
    {
        cout << "constructing B" << endl;
    }
    ~B()
    {
        cout << "destructing B" << endl;
    }
private:
    int b;
    C c;
};

void main()
{
    B b;
}

运行结果

constructing A
constructing C
constructing B
destructing B
destructing C
destructing A
#include<iostream>
using namespace std;
class Date {
private:
	int year, month, day;
public:
	Date(int y = 2009, int m = 1,int d = 1);  //带有参数的构造函数
	Date(const Date &date);                   //拷贝构造函数声明,形参是对象                          
//析构函数定义
~Date()
{
	cout << "调用析构函数..." << endl;
}
void showDate();
};

Date::Date(int y, int m, int d)//构造函数定义
{
	year = y;
	month = m;
	day = d;
	cout << " 调用构造函数..." << endl;
}

Date::Date(const Date& date1)//拷贝构造函数的定义
{
	year = date1.year;
	month = date1.month;
	day = date1.day;
	cout << "调用复制构造函数..." << endl;
}
void Date::showDate()//输出函数定义
{
	cout << year << "." << month << "." << day << endl;
}
Date Fun(Date date2)
{
	Date date3(date2);
	return date3;
}
int main() 
{
	Date o1(1999, 3, 20);//调用带参构造方法
	Date o3;//调用构造方法,使用默认参数值
	Date o2(o1);//调用拷贝构造函数
	Date o4 = o2;//调用拷贝构造函数
	o3 = o2;//调用拷贝构造函数
	o3 = Fun(o2);//Fun函数内部创建date3时调用一次拷贝构造函数,对象作为返回值返回时调用一次构造函数
	
	o3.showDate();//输出函数输出对象的值

	return 0;
}

 运行结果

10. 浅拷贝和深拷贝

  • 浅拷贝: 就是由默认的拷贝构造函数所实现的数据成员逐一复制(若类中含有指针类型的数据,这种按数据成员逐一赋值的方法将会产生错误
  • 深拷贝: 不是复制指针本身,而是复制指针所指向的动态空间中的内容.实现了两个对象的指针成员拥有不同的地址值,指向不同的动态存储空间首地址,而且两个动态空间中的内容完全一样
两者的区别和联系
  • 两者都是实现复制
  • 在不涉及指针的拷贝时两者没有差别
  • 深拷贝重新分配了空间,改变被拷贝对象时拷贝对象不会改变
内存泄漏
  • 当实现浅拷贝时,只是将被拷贝对象的地址复制给了拷贝对象,两个对象指向同一个空间,并没有创建新的空间给新的对象,在调用析构函数清除空间时,同一个空间被清除两次,在第二次清除的时候,析构对象找不到释放的空间,就会产生内存泄漏.
class Test
{
private:
    int* p;
public:
    Test(int x)
    {
        this->p=new int(x);
        cout << "对象被创建" << endl;
    }
    ~Test()
    {
        if (p != NULL)
        {
            delete p;
        }
        cout << "对象被释放" << endl;
    }
    int getX() { return *p; }
    //深拷贝(拷贝构造函数)
    Test(const Test& a)
    {
        this->p = new int(*a.p);
        cout << "对象被创建" << endl;
    }
    //浅拷贝(拷贝构造函数)
    //Test(const Test& a)
    //{
    //  this->p = a.p;
    //  cout << "对象被创建" << endl;
    //}
};

int main()
{
    Test a(10);
    //我们手动的写拷贝构造函数,C++编译器会调用我们手动写的
    Test b = a;
    return 0;
}

11. UML(Unifined Modeling Language)统一建模语言

11.1 UML类型
  • 类图,顺序图,协作图,类图,对象图,状态图,活动图,构件图和部署图
11.2 类图
  • 类图是由类和与之相关的各种静态关系共同组成的图形
  • 类图展示是软件模型的静态结构,类的们内部结构和其他类之间的关系
  • 类图中最基本的是图形化描述类,要表示类的名称,数据成员和成员函数以及各成员的访问控制属性
11.3 类和对象
  • 类名写在顶部区域
  • 数据成员: 在中间区域
    • 访问控制属性: public “+”, private “-”,protected “#”
    • 名称: 是标识数据成员的字符串
    • 类型:表述数据成员的类型
    • 默认值: 赋予该数据成员的初始值
    • 约束特征: 用户对该数据成员性质的约束说明
  • 成员函数: 在底部区域
    • 访问属性
    • 名称
    • 参数表
    • 返回类型
    • 约束特性
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值