前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >类和对象(1)

类和对象(1)

作者头像
用户11039545
发布2024-07-25 14:22:50
620
发布2024-07-25 14:22:50
举报
文章被收录于专栏:c语言

面相过程和面向对象区别

c语言就是面向过程的语言,即关注的是过程的求解,我们利用函数逐步解决问题。

c++是面向对象的语言。将一件事情拆分成不同的对象,靠的是对象之间的关系完成。

类的引入

c++中结构体不仅可以定义变量,还能定义函数,而在c语言中结构体只能定义变量。现在以c++方式实现,发现struct也可以定义函数。

类的定义

代码语言:javascript
复制
class ClassName
{
  //由成员函数和成员变量组成
};

类体中的内容称为类的成员,类的变量称为类的属性或成员变量,类中的函数称为类的方法或成员函数。

类的定义方式

1类的声明和定义全部放在类体当中,需要注意的是,如果函数在类中定义,编译器可能会将其当作内联函数处理。

代码语言:javascript
复制
class Person
{
  public:
    void ShowPeoInfo()
    {
       cout<<_name<<"-"<<_age<<"-"<<_sex<<endl;
    }
 public:
    char* _name;
    char* _sex;
    int age;
};

2类的声明放在头文件中,类的函数放在源文件当中。注意:成员函数之前需要加类名::

声明放在person.h文件当中 

代码语言:javascript
复制
class Person
{
  public:
    void ShowPeoInfo();
  public:
    char* _name;
    char* _sex;
    int age;
}:

person.cpp

注意:成员函数前需要加上类名

代码语言:javascript
复制
#inlcude<person.h>
void Person::ShowPeoInfo()
{
   cout<<_name<<"-"<<_age<<"-"<<_sex<<endl;
}

成员命名规则的建议:

代码语言:javascript
复制
Class Date
{
  public:
     void Init()
     {
        year=year;
      }
  private:
     int year;
};

这里有一个问题,那就是这里的year到底是成员变量还是函数形参?

我们应该用如下方式命名变量:

代码语言:javascript
复制
Class Date
{
  public:
     void Init()
     {
        year=_year;
      }
  private:
     int _year;
};

类的访问限定符以及封装

c++用类的方法将对象的属性和方法放在一起,通过选择性地将接口提供给外部使用来实现封装。

访问限定符的作用域是从这个访问限定符开始到下一个访问限定符

class的默认访问权限为private,struct的默认访问权限为public。

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

封装

面向对象的三大特点:封装,继承,多态

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

类的作用域

类定义了一个新的作用域,在类体外定义成员时,需要用域作用限定符::指明成员属于哪个类域。

类的实例化

用类类型创建对象的过程,称为类的实例化。

1 类是对对象进行描述的,定义出一个类并没有实际的空间储存它

2 一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量

代码语言:javascript
复制
int main()
{
  Person._age=100;
  return 0;
}

// 编译失败:error C2059: 语法错误:“.”

Person类是没有空间的,只有person实例化出的对象才有物理空间。

类对象模型 

类中既可以有成员变量,又可以有成员函数,那么一个类的对象中包含了什么?如何计算一个类的大小?

结论:一个类的大小,就是成员变量之和,注意内存对齐。

空类比较特殊,编译器给了空类一个字节来唯一标识这个类的对象。

this指针

代码语言:javascript
复制
class Date
{ 
public:
 void Init(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 void Print()
 {
 cout <<_year<< "-" <<_month << "-"<< _day <<endl;
 }
private:
 int _year;     // 年
 int _month;    // 月
 int _day;      // 日
};
int main()
{
 Date d1, d2;
 d1.Init(2022,1,11);
 d2.Init(2022, 1, 12);
 d1.Print();
 d2.Print();
 return 0;
}

这里有一个问题,Date中有两个成员函数,Init和Print,函数体中没有不同对象的区分,那么当d1调用Init函数时候,如何知道不是d2而是d1对象调用的呢?

c++中通过引入this指针来解决这个问题:

c++给每个非静态的函数一个this指针,通过指向当前对象(函数运行时调用的对象),所有成员变量的操作,都是通过指针去访问。只不过所有操作都是编译器自己完成的,不需要用户来操作。

例如:d1.Init(&d1,2022,1,11);会将地址传递过去。

前面还有一个指针:

代码语言:javascript
复制
void Init(int year, int month, int day)
 {
 this->_year = year;
 this->_month = month;
 this->_day = day;
 }

特性

1 类类型*const,不能给this指针赋值(const*修饰的是指向的对象,*const修饰的是指针本身)

2 本质上是成员函数的形参,当对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针

3 this指针是成员函数的第一个形参,一般由编译器ecx自动传递

比如Date类的Init类的真实原型为:

代码语言:javascript
复制
void Init(Date* const this,int year,int month,int day)

this指针存在内存的哪个区域?

E一定不对,因为刚刚我们算对象大小的时候就没有算this指针。

选A

下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

代码语言:javascript
复制
class A
{
public:
 void Print()
 {
 cout << "Print()" << endl;
 }
private:
 int _a;
};
int main()
{
 A* p = nullptr;
 p->Print();
 return 0;
}

空指针不可能是编译错误,最多是运行崩溃。这个题是A正常运行,为什么呢?这里不是有空指针吗?

编译器编译以后,都会转换为汇编指令。 p->Print();这句代码转换成的编译指令是call 地址。地址不在p对象里(成员函数的指针不存到对象里面)。为什么需要p调用呢?因为Print()是内域,是成员函数,编译的时候就知道去Class A里面找,这里不需要取地址,因为p就是对象的地址//mov ecx p(ecx存的是this指针)。把p传给了this,this是空指针。cout<<this<endl;空指针没有解引用,并不会报错。如果是p->_a=1;这个时候成员变量被引用,就崩溃了。

 下面程序编译运行结果是? A、编译报错 B、运行崩溃 C、正常运行

代码语言:javascript
复制
class A
{ 
public:
    void PrintA() 
   {
        cout<<_a<<endl;
   }
private:
 int _a;
};
int main()
{
    A* p = nullptr;
    p->PrintA();
    return 0;
}

这个题目的答案是B。相当于解引用了。

C语言和C++实现Stack的对比

c语言

c语言在实现函数时,操作函数有以下特性:

1每个函数的第一个参数都是Stack*

2函数中必须要对第一个参数检测,第一个参数是NULL

3函数都要通过Stack*操作栈

4 调用时必须穿Stack结构体变量的地址

结构体内只能存放数据的结构,操作数据的方法不能放在结构体当中,即数据和数据操作的方式是分开的。

c++

c++中通过类,可以将数据以及操作数据的方法完美结合,通过访问权限可以控制那些方法在类外的函数可以被调用,即封装。C++中 Stack *是编译器自己维护的,而c语言中是需要用户进行维护的。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 面相过程和面向对象区别
  • 类的引入
  • 类的定义
    • 类的定义方式
    • 类的访问限定符以及封装
      • 封装
        • 类的作用域
          • 类的实例化
          • 类对象模型 
          • this指针
            • 特性
              • C语言和C++实现Stack的对比
                • c语言
                • c++
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档