浅显易懂的《C++类与对象》-上篇

目录

1.面向过程和面向对象的认识

2.类的引入和定义

1.类和对象的概念和使用

2.访问限定符

3.类的两种定义方式

4.成员变量命名规则的建议

3.封装

4.类的作用域

5.实例化对象

6.类对象的大小

7.this指针


1.面向过程和面向对象的认识

面向过程,关注的是求解问题的步骤,通过函数调用逐步解决问题

面向对象,关注的是对象,拆分成不同的对象,每个对象有独自的作用,靠对象之间的交互完成

2.类的引入和定义

1.类和对象的概念和使用

类就是C语言中学到的struct的进阶,类既可以包括成员变量(类的属性),也可以包括成员函数(类的方法),可以写struct,也可以写class作为类关键字。

写类名来定义对象,当然C++仍然兼容C结构体的原始用法,可以写struct 类名 对象名,或者class 类名 对象名,严格编译器是不可以在定义时写成class 类名 对象名,vs可以。

C++把struct升级成了类,使用以及成员变量定义时不用写struct,直接写类名刚开始不知道起什么名字,就用struct代替,C++推荐使用class。

2.访问限定符

访问限定符是限制类外面访问,限定符向下为作用域,遇到另一个限定符停止,通过类访问限定符protected、private、public划分struct与class的区别,如果类中中的成员没有设置类访问限定符,struct默认设置public,class默认设置private,这里介绍private是类声明外,即大括号外没有访问权限,protect相似于private,当然protect当前阶段不讲解,先使用private。

注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别

class Person
{
public:
    void showInfo()
    {
        cout << _name << "-" << _sex << "-" << _age << endl;
    }
private:
    char* name;
    char* sex;
    int _age;
};
int main()
{
    Person* a;//与结构体相似,可以使用->来指定需要访问的成员
}

注意:C++类的成员变量可以写在成员函数下面是因为C++把类当成一个整体,搜索时不分上下。

函数不写参数是因为有隐式this指针,这也是类的好处,不需要传参就可以使用成员变量更加简洁有力,this指针下面会讲。

3.类的两种定义方式

1. 声明和定义全部放在类体中,需注意:类中的成员函数如果直接定义,默认是内联函数。

2. 类声明放在.h文件中,成员函数定义放在.cpp文件中,类声明和定义分明是为了方便阅读,代码量大,不容易看逻辑,在源文件中不需要重写整个类,只用写需要实现的成员函数,使用域作用限定符::来定义成员函数更期望采用第二种方式。

//头文件(声明)
class Person
{
public:
    void showInfo();
private:
    char* name;
    char* sex;
    int _age;
};

//源文件(定义)
void Person::showInfo()
{
    cout << _name << "-" << _sex << "-" << _age << endl;
}

4.成员变量命名规则的建议

C++惯例成员变量名前加_或后_,建议用前_,是为了区分函数参数重名问题。

class Date
{
public:
    void Init(int year)
    {
        // 这里的year到底是成员变量,还是函数形参?
        year = year;
    }
private:
    int year;//正确:_year
};

3.封装

面向对象的三大特性:封装、继承、多态。

封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来
和对象进行交互。

封装本质上是一种管理,让用户更方便使用类。

C语言的访问是自由的,C++封装本质是一种管理,更安全,更规范。

调用函数(接口)是为了规范,可读性,防止出错,比如栈成员top初始化可能为-1,也可能为0,st.a[st.top]会出错,所以不让类外访问的成员设置私有,可以访问的成员设置公有。

4.类的作用域

类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员时,需要使用 ::
作用域操作符指明成员属于哪个类域,例如生命与定义分明,源文件中需要使用::。

5.实例化对象

类定义对象的过程就是实例化对象类是声明,对象是定义,不能通过类名::来初始化,声明是没有分配空间的。

6.类对象的大小

成员函数存储于数据段(常量区),因为公共使用的函数(存在于公共代码区域)不需要根据对象的不同再重新创建栈帧,从而浪费空间和时间。

成员变量与结构体一样存在内存对齐,例如:char c;int a;类对象的大小就为8。

空类里没有成员变量,内存大小为1,不存储有效数据,占位,标识对象存在。

7.this指针

this:(隐式)对象的指针

1. this指针的类型:类类型* const,即成员函数中,不能给this指针赋值。
2. 只能在“成员函数”的内部使用。
3. this指针本质上是“成员函数”的形参,当对象调用成员函数时,将对象地址作为实参传递给
this形参。所以对象中不存储this指针。
4. this指针是“成员函数”第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传
递,不需要用户传递。

5.this指针存在于栈区,跟着栈帧开辟

通过两道编程进行判断,要想真正的学会this指针这一步是不得不学。

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
    void Print()
    {
    cout << "Print()" << endl;
    }
private:
    int _a;
};
int main()
{
    A* p = nullptr;
    p->Print();
    return 0;
}

// 1.下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行
class A
{
public:
    void PrintA()
    {
    cout<<_a<<endl;
    }
private:
    int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

解析:

 成员函数是存在于数据段中,对于程序编译而言是看得见摸得着的,就在头顶,所以p->PrintA()是不发生解引用的,因为成员函数的地址不在对象中,在公共代码区域,所以答案为C。

其次,this就是p,p为nullptr,void PrintA的参数是隐性this指针,类型为A* const this,因为this指向的是p这个对象,并且对象不能够被改变,所以用const修饰增加安全性。函数作用域内,其实

_a是this->_a,这个可以写也可以不写,编译器编译时会自动加上,写了编译器就不会加,有了这个概念,this为nullptr,程序必然会崩溃,所以答案为B。

所以,C++的封装、类访问权限设置等,相比于C传参数存在的错误隐患,C++的类更加方便简洁,C面向过程与C++相比,C++的对象访问更加规范,可读性也提高了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值