C 语言被认为是面向过程的编程语言,在面向过程的编程中,重点在于程序功能的实现,通过函数调用逐步解决问题。
C++ 是面向对象的,编程强调的是将数据和对数据的操作封装在对象中,通过类和对象的概念来组织程序结构,实现数据的隐藏、继承和多态等特性。
类是一种用户自定义的数据类型,它将数据(成员变量)和操作这些数据的函数(成员函数)封装在一起,形成一个逻辑上相关的单元。
class 类名 {
访问修饰符:
成员变量;
成员函数;
};
为了区分成员变量,⼀般习惯上成员变量会加⼀个特殊标识,如成员变量前⾯或者后⾯加_或者m 开头,注意C++中这个并不是强制的,只是⼀些惯例,具体看公司的要求。
C++中struct也可以定义类,C++兼容C中struct的⽤法,同时struct升级成了类,明显的变化是 struct中可以定义函数,⼀般情况下我们还是推荐⽤class定义类。
注意:定义在类里面的成员函数默认为inline(内联函数)。
C++ 实现封装的方式: 用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选
择性的将其接口提供给外部的用户使用。
在C++ 中有有三种访问限定符:public(公共的),private(私人的),protected(受保护的)。
class Date
{
public://公开的
void Init(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
private://私有的
int _year;
int _month;
int _day;
};
拓展:struct默认为public;
在 C 语言中,对于结构体内部指针指向自身类型,需要使用 struct
关键字来标识,就像代码 1 中struct List* next;
这样。而在 C++ 中,可以直接使用结构体的名称,如代码 2 中的List* next;
。C++ 对结构体的处理方式更加灵活和方便,在结构体内部引用自身类型时无需再重复使用 struct关键字。
//代码1,c语言的写法
struct List
{
int val;
struct List* next;
};
//代码2,c++的写法
struct List
{
int val;
List* next;
};
类定义了⼀个新的作⽤域,类的所有成员都在类的作⽤域中,在类体外定义成员时,需要使⽤::作 ⽤域操作符指明成员属于哪个类域。c++常用的四个域:局部域,全局域,命名空间域,类域。
#include<iostream>
using namespace std;
class Date
{
public:
//成员函数
void Init(int year = 1, int month = 1, int day = 1);
private:
//成员变量
int _year;
int _month;
int _day;
};
//声明和定义分离,需要指定类域
//这里是☞Date这个类域下的Init函数
void Date::Init(int year = 1, int month = 1, int day = 1)
{
_year = year;
_month = month;
_day = day;
}
int main()
{
Date d1;
d1.Init();
return 0;
}
⽤类类型在物理内存中创建对象的过程,称为类实例化:
就像建造一个房子之前需要设计图,设计完之后才能将房子建造出来(实例化),可以将这个设计的房子。
int main()
{
//实例化出对象d1,d2,d3,d4
Date d1;
Date d2;
Date d3;
Date d4;
return 0;
}
类和对象的内存对齐和struct几乎一模一样,对齐规则
如果还不清楚可以看看之前写的:C语言结构体 。
#include<iostream>
using namespace std;
//含有成员函数和成员定义
class A
{
public:
void print()
{
cout << " print()" << endl;
}
private:
char a1;
int a2;
};
//含有成员函数
class B
{
public:
void print()
{
cout << " print()" << endl;
}
};
//无
class C
{};
//嵌套
class D
{
public:
class E{
int b;
};
private:
int a;
};
int main()
{
A a;
B b;
C c;
D d;
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
cout << sizeof(c) << endl;
cout << sizeof(d) << endl;
return 0;
}
c
上⾯的程序运⾏后,我们看到没有成员变量的B和C类对象的⼤⼩是1,为什么没有成员变量还要给1个 字节呢?因为如果⼀个字节都不给,怎么表⽰对象存在过呢!所以这⾥给1字节,纯粹是为了占位标识 对象存在。
类D中,我们嵌套了E,但是实际只有4个字节,这是因为嵌套类E的成员变量并不直接包含在类的内存布局中。嵌套类是一个独立的类,它的成员变量的存储与外部类是相互独立的。
QiuQiu类中Print函数和默认构造函数,这两个成员中没有关于对象的区分,可为什么在调用时,却能够区分q1和请q2。其实这是C++在类中给了一个隐含的this指针来解决这里的问题。
编译器编译后,会在函数的第一个位置放置一个默认的成员函数,叫做this指针,且这个不需要我们手动去写。
C++规定不能在实参和形参的位置显⽰的写this指针(编译时编译器会处理),但是可以在函数体内显示使⽤this指针。
#include<iostream>
using namespace std;
class QiuQiu
{
public:
//QiuQiu (QiuQiu* const this, int age, int height, int weight)
QiuQiu (int age, int height, int weight)
{
_age = age;
this->_height = height;
this->_weight = weight;
}
//void Print(QiuQiu* const this) --q1 / q2
void Print()
{
cout << "年龄:" << _age <<"岁" << endl;
cout << "身高:" << _height << "厘米" << endl;
cout << "体重:" << _weight << "千克" << endl << endl;;
}
private:
int _age;
int _height;
int _weight;
};
int main()
{
QiuQiu q1(20,180,65);
q1.Print();
cout << endl;
QiuQiu q2 (15,170,55);
q2.Print();
return 0;
}
注意:this指针跟普通指针一样都是放在栈区域上的。
下⾯程序编译运⾏结果是()
A、编译报错 B、运⾏崩溃 C、正常运⾏
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "A::Print()" << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
A*p =nullptr;将p的地址就是this指针,而类中的成员函数放在公共代码段中,只是被类所限制访问。虽然表面上失去解引用,但printf()这个成员函数在编译的时候地址就以及确定了,之后只需要找到对应的函数即可,实际上并没有解引用。
下⾯程序编译运⾏结果是()
A、编译报错 B、运⾏崩溃 C、正常运⾏
#include<iostream>
using namespace std;
class A
{
public:
void Print()
{
cout << "A::Print()" << endl;
cout << _a << endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Print();
return 0;
}
_a存在对象里面,p为空,this指针也就为空,对空指针进行解引用,会产生运行奔溃。