C++知识点---类和对象

更多知识点请点击:C++知识点目录索引
1. 类和对象
  • 类:和结构体类似,存在数据(变量),还有方法(函数),即类包含成员变量和成员函数

  • 对象:类的实例,将对象作为程序的基本单元,将程序和数据封装其中,以提高软件的重用性、灵活性和扩展性。


2. 类和对象的特点
  • 类:具有封装性,将变量和函数封装到类当中,类的访问限定符(public、private、protected)体现了面向对象的封装性

  • 对象:封装,继承,多态


3. 具体例子
3.1 类的定义
//类内定义成员函数
class Person
{
public:
    void Show()//可以直接从类外部访问,作用域为:到下一个public,或者类结束
    {
        cout<<_name<<endl;
        cout<<_sex<<endl;
        cout<<_age<<endl;
    }
private://不可直接从类外部访问
    char* _name;
    char* _sex;
    int _age;
}


//类外定义成员函数
class Person
{
public:
    void Show();//可以直接从类外部访问,作用域为:到下一个public,或者类结束
private://不可直接从类外部访问
    char* _name;
    char* _sex;
    int _age;
}

void  Date::Show()//类外写成员函数必须指明函数属于哪一个类域
{
    cout<<_name<<endl;
    cout<<_sex<<endl;
    cout<<_age<<endl;
}
3.2 实例化:
class Person
{
public:
    void Show()
    {
        cout<<_name<<endl;
        cout<<_sex<<endl;
        cout<<_age<<endl;
    }
private:
    char* _name;
    char* _sex;
    int _age;
}


void Test()
{
    Person P;//类的对象
    p._name = "张三";
    P._sex  = "男";
    P._age = 10;
}

4. 类的作用域:
  • 成员函数和成员变量都在类的作用域内,类内部成员可直接访问

  • 类外定义成员,使用::表示在哪个作用域

例:

//类的声明
class Person
{
Public:
    void show();
privatechar* _name;
    int _age;
}

//定义
Person::show()
{
    cout<<_name<<endl;
    cout<<_age<<endl;
}

5. 类的大小:
  • 和结构体内存对齐规则一致

  • 只取决于成员变量的大小,成员函数不占对象空间(原因:将成员函数放在公共代码区,供大家使用)

  • 空类的大小为1,开辟一个空间表示类的存在

  • 内存对齐规则

  • 第一个成员在与结构体变量偏移量为0的地址处。
  • 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
    对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
    VS中默认的值为8
    Linux中的默认值为4
  • 结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
  • 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

6. 内存对齐的原因
  • 由于存在内存访问机制,每次访问内存时从0号地址处连续读取4字节(或4字节的整数倍);

  • 如果不存在内存对齐,读取一个变量时会读取两次或者三次甚至更多,反而降低效率

  • 内存对齐的前提下,读取一次即可提高效率


7. this指针
  • 每个成员函数都有一个指针形参,它的名字是固定的,称为this指针,this指针是隐式的。(构造函数比较特殊,没有这个隐含this形参)

  • 编译器会对成员函数进行处理,在对象调用成员函数时,对象地址作实参传递给成员函数的第一个形参this指针。

  • this指针是成员函数隐含指针形参,是编译器自己处理的,我们不能在成员函数的形参中添加this指针的参数定义,也不能在调用时
    显示传递对象的地址给this指针。
    类的

void show();//原本成员函数

void show(Date* this);//编译器处理的成员函数

8. 默认成员函数
8.1 构造函数
  • 没有返回值,可以有参数,没有参数的构造函数被认为是缺省构造函数,但缺省构造函数只允许有一个

  • 与类同名,可以有多个构造函数 ,可以重载, 没有隐含的this形参

  • 作用是将对象初始化,创造出对象时系统自动调用构造函数进行对象的实例化

例:

class Date
{
public:

//两个缺省参数只可取其一

    Date();//(1)类内声明


    /*Date(int year=1900,int month=1,int day=1)//(2)类内定义
    {
        _year=year;
        _month=month;
        _day=day;
    }*/

    void show()
    {
        cout<<_year<<endl;
        cout<<_month<<endl;
        cout<<_day<<endl;
    }
private:
    int _month;
    int _year;
    int _day;
}

//类外定义:
Date::Date()
{
    _year=1900;
    _month=1;
    _day=1;
}

注意:如果没有定义构造函数,编译器会自己生成默认缺省构造函数(无参的构造函数),如果是成员变量是内置类型,默认构造函数不会初始化,如果成员变量是自定义类型,自动生成的默认构造函数调用自定义类型的构造函数进行初始化

例:

//自定义类型
class Time
{
public:
    Time()//自定义类型的构造函数
    {
        cout<<_hour<<endl;
    }
private:
    int _hour;
}
class Date
{
public://无构造函数,生成默认的缺省构造函数(无参的构造函数),什么也不做(成员函数有自定义类型除外)
    void show()
    {
        cout<<_year<<endl;
        cout<<_month<<endl;
        cout<<_day<<endl;
    }
private:
    int _month;
    int _year;
    int _day;//默认生成的构造函数不会对齐初始化
    Time _t;//调用自定义类型的构造函数对其进行初始化
}



8. 2 析构函数
  • 与类同名,并且与构造函数工作性质相反,故有~ 标识析构函数

  • 当对象生命周期结束(即出了类的作用域),系统自动调用析构函数

  • 不支持重载,完成清理工作(动态开辟),保证对象的初始化和销毁

例:

class SeqList
{
public:
    SeqList(size_t  capacity=0)//构造函数
    {
        if(capacity > 0)
        {
            _a=(int*)malloc(sizeof(int)*capacity);
            _capacity=capacity;
            _size=0;
        }
        else
        {
            _a=NULL;
            _capacity=_size=0
        }

    }

    ~SeqList()//析构函数
    {
        free(_a);
        _size=_capacity=0;
    }

private:
    int*  _a;
    size_t _size;
    size_t _capacity;

}

8.3 拷贝构造函数
  • 参数是一个同类型的对象,使用同类对象进行初始化

  • 拷贝构造函数使用引用

  • 如果没有定义拷贝构造函数,系统自动生成缺省拷贝构造函数并进行初始化

例:

class Date
{
public:

    Date(int year=1900,int month=1,int day=1)//缺省参数
    {
        _year=year;
        _month=month;
        _day=day;
    }

    Date(const Date& d)//加引用,防止无限递归
    {
        _year=d._year;
        _month=d._month;
        _day=d._day;
    }
    void show()
    {
        cout<<_year<<endl;
        cout<<_month<<endl;
        cout<<_day<<endl;
    }
private:
    int _month;
    int _year;
    int _day;
}

8.4 运算符重载
  • 作用:增强代码的可读性

  • 特征:operator + 运算符(例:operator<)

  • 不能重载的运算符: .* :: sizeof ?: :

  • 两种形态:成员函数(一个参数,还有一个隐含的this),全局

例:

class Date
{
public:

    Date(int year=1900,int month=1,int day=1);//缺省参数
    Date(const Date& d);//加引用,防止无限递归
    void show();
    bool operator==(const Date& d1,const Date& d2);//类内声明
private:
    int _month;
    int _year;
    int _day;
}

//全局
bool Date::operator==(const Date& d1,const Date& d2)
{
    return d1._year==d2._year 
        && d1._month==d2.month
        && d1._day==d2._day;
}


//成员函数

class Date
{
public:

    Date(int year=1900,int month=1,int day=1);//缺省参数
    Date(const Date& d);//加引用,防止无限递归
    void show();
    bool operator==(const Date& d1,const Date& d2);//成员函数
    {
        return d1._year==d2._year
            && d1._month==d2.month
            && d1._day==d2.day;
    }
private:
    int _month;
    int _year;
    int _day;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值