C++类与对象(上)


目录

1.面向过程与面向对象

2.类的引入

3.类的定义

4.类的访问限定符

5.封装思想

6. 类的实例化与对象

 7.this指针

概念:

性质:

经典例题


1.面向过程与面向对象

不难发现在学习C语言时我们经常在写各种各样的函数,例如交换、排序、比较,这些函数是我们解决问题的方法,也是我们解决问题的过程。而在C++中引入了类与对象的概念后,之前我们写的函数可以封装在类中,许多问题就可以交给这些类去解决。

2.类的引入

C语言结构体中可以定义多个类型的变量。在C++中对结构体进行了升级,结构体中还可以定义函数,若是结构体中定义了函数,则其就是一个类,类的类型就是结构体的名称。

但是这其实是一种兼容C的写法。

3.类的定义

C++更为主流的写法是使用class关键字来定义类

//class后加类名
class classname{
   //类体

   //类中的方法叫作成员方法
   void Print(){
    
   }   

   //类中的变量叫作成员变量
   int age;
};

类中的成员方法有两种声明定义方式:1.声明定义分离,假如类在.h中,且方法在类中只进行了声明,方法的定义在.cpp中,则.cpp除了需要包含.h之外,还需要在方法名前加上类名::(类会产生类域)。2.声明定义都在类中,编译器可能会把其当成内联函数。

4.类的访问限定符

当我们像使用struct一样去使用class发现了下面的问题,why?

原因:class中默认添加了访问限定符private,只允许在类中访问,而前面的struct能访问是因为struct的默认访问限定符是public。

访问限定符介绍:public修饰的成员类外可以访问,private和protect修饰的成员类外无法访问。

访问限定符修饰范围:从当前限定符到下一个限定符,若没有下一个,则到右花括号}。

5.封装思想

将一个类的属性和方法封装到一起,部分方法对外开放,其余方法和属性只能在类内部进行访问,外界想访问属性时只能按照类所给方法访问,这样做可以很好的保护类的内部成员。

6. 类的实例化与对象

类就像一个设计图,而对象则是根据这个设计图设计出来的产品,当对类进行实例化就产生了对象。

类中既可以有成员变量,又可以有成员函数,那么一个类的大小怎么计算呢?我们来看看下面三种情况。


class A {
public:
    void f1(){}
private:
    int _a;
};

class B {
public:
   void f2() {}
};

class C
{}

经过sizeof()验证,A的大小是4B,B类大小是1B,C类的大小是1B。

结论:类的大小等于成员变量在内存上根据内存对齐规则后的"和";类的对象的成员函数共用一块空间,计算对象大小时成员函数不做计算;特殊的,空类的大小为1B。

补充:

结构体对齐规则:

1. 第一个成员在与结构体偏移量为0的地址处。

2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

    注意:对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。

    VS中默认的对齐数为8

3. 结构体总大小为:最大对齐数(所有变量类型最大者与默认对齐参数取最小)的整数倍。

4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

 7.this指针

概念:

C++编译器给每个类中的“非静态的成员函数“增加了一个隐藏的指针参数this,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有“成员变量” 的操作,都是通过该指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。

性质:

1.this指针实质上是调用成员函数的对象的地址

2.在类的成员函数中默认this指针为第一个参数

3.this指针的类型为const classname(类名)*,即不可改变this指针的值

4.this指针只存在成员函数内部

class A{
   //参数列表中隐藏了this->(const A* this)
   void print(){
   
   //cout<<this->age<<endl;与下句代码等价
   cout<<age<<endl;
   
   }   

   int age;
}
经典例题
class B
{
public:
 void Print()
 {
 cout << "Print()" << endl;
 }
private:
 int _a;
};

int main()
{
 B* ptr = nullptr;
 ptr->Print();
 return 0;
}

此处可以正常运行,因为前面说过成员函数不存储在对象中,所以尽管此处调用Print()函数,但是不会对ptr解引用,而是直接调用类公共区域内的成员函数然后将ptr作为实参传递给形参this,无语法错误和运行错误。

class C
{ 
public:
    void PrintC() 
   {
        cout<<_a<<endl;
   }
private:
 int _a;
};
int main()
{
    C* ptr = nullptr;
    ptr->PrintC();
    return 0;
}

此处会报错。调用成员函数前的过程和上题一样不会出错,可是进入成员函数PrintC()后,_a(等价于this->a)需要对this指针进行解引用操作,而this指针此时为空,无法解引用,所以此处会有运行错误。

  • 23
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值