面向过程和面向对象初步认识
面向过程
C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。
面向对象
C++是基于面向对象的,关注的是对象,将一件事情拆分成不同的对象,靠对象之间的交互完成。
类的引入
在C语言中,结构体中只能定义变量。
在C++中,兼容C语言的
struct
用法,同时对struct
进行了升级,把struct
升级成了类1、结构体名字做类型
2、结构体内可定义函数
struct Student { void SetStudentInfo(const char* name, const char* gender, int age) { strcpy(_name, name); strcpy(_gender, gender); _age = age; } void PrintStudentInfo() { cout << _name << " " << _gender << " " << _age << endl; } char _name[20]; char _gender[3]; int _age; }; int main() { Student s;//C++中,可以直接用结构体名字做类型 s.SetStudentInfo("Peter", "男", 18); return 0; }
上面结构体的定义,在C++中更喜欢用class代替
类的定义
class className { // 类体:由成员函数和成员变量组成 };
class
为定义类的关键字,className
为类的名字,{}
中为类的主体,注意类定义结束时后面分号。类中的元素称为类的成员;
类中的数据称为类的属性或者成员变量;
类中的函数称为类的方法或者成员函数;
类的两种定义方式:
1、声明和定义全部放在类体中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理。
2、声明放在
.h
文件中,类的定义放在.cpp
文件中注意:一般情况下,更期待采用第二种方式。
类的访问限定符及封装
访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其 接口提供给外部的用户使用。
【访问限定符说明】
1、public修饰的成员在类外可以直接被访问
2、protected和private修饰的成员在类外不能直接被访问(此处protected和private是类似的)
3、访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4、
class
的默认访问权限为private
,struct
为public
(因为struct
要兼容C) 注意:访问限定符只在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
封装
面向对象的三大特性:封装,继承,多态。
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
类的作用域
类定义了一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用 :: 作用域解析符 指明成员属于哪个类域。
class Person { public: void PrintPersonInfo(); private: char _name[20]; char _gender[3]; int _age; }; // 这里需要指定PrintPersonInfo是属于Person这个类域 void Person::PrintPersonInfo() { cout<<_name<<" "_gender<<" "<<_age<<endl; }
类的实例化
用类类型创建对象的过程,成为类的实例化
1、定义一个类并没用分配实际的内存空间来存储它(不能存储数据)
2、一个类可以实例化出多个对象,实例化出的对象占用实际的物理空间,存储类成员变量(可以存储数据)
注意:
1、在使用类定义对象时,开辟空间,这块空间内只有成员变量,函数在公共代码区。定义同一类的多个对象时,他们调用的函数是同一个函数,在公共代码区。调用函数时,函数有一个隐含的this指针(不能显示写出)
2、因为类对象中只有成员变量,所以计算大小时只计算成员变量的大小(按照结构体内存对齐规则计算大小)
class A { public: void Print() { cout << "qwer" << endl; } private: int a; double b; char c; }; int main() { A a; cout << sizeof(a) << endl;//输出24 return 0; }
this指针
概念
C++编译器给每个“非静态的成员函数“增加了一个隐藏的指针参 数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该 指针去访问。只不过所有的操作对用户是透明的,即用户不需要来传递,编译器自动完成。
this指针的特性
1、this指针的类型:类类型*
const
2、 只能在“成员函数”的内部使用
3、 this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this 形参。所以对象中不存储this指针。
4、 this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过
ecx
寄存器自动传递,不需要用户传递
面试题
// 1.下面程序能编译通过吗?
// 2.下面程序会崩溃吗?在哪里崩溃
class A
{
public:
void Show()
{
cout<<"Show()"<<endl;
}
private:
int _a;
};
int main()
{
A* p=nullptr;
p->show();//show()成员函数不在对象p内,所以调用函数不会解引用
return 0;
}
1、编译通过
2、运行成功
// 1.下面程序能编译通过吗?
// 2.下面程序会崩溃吗?在哪里崩溃
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
private:
int _a;
};
int main()
{
A*p=nullptr;
p->PrintA();//在调用函数时,函数内需要访问成员变量的值,需要对p解引用,p为空指针,空指针不是有效地址,无法解引用,程序崩溃
}
1、编译通过
2、运行崩溃
问:this指针存在哪里?
一般是在栈上,有些编译器会使用寄存器优化
问:this指针可以为空吗?
可以为空
补充:空指针是什么?
空指针是
(0x00000000)
,
0x00000000
是预留出来的,不存储数据,不是有效地址。