目录
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指针此时为空,无法解引用,所以此处会有运行错误。