一、类的定义
class为定义类的关键字,ClassName为类的名字,{}中为类的主体。类中的元素称为类的成员:类中的数据称为类的属性或者成员变量; 类中的函数称为类的方法或者成员函数。类定义出来的变量称为对象。C++兼容C中结构体struct的用法同时在C++中升级为类class。
#include <iostream>
using namespace std;
struct people {
//成员变量
char _name[10];
int _age;
//成员函数
void init(const char* name,int age)
{
strcpy(_name,name);
_age=age;
}
void print()
{
count<<_name<<endl;
count<<_age<<endl;,
}
};
int main()
{
struct people p1;//兼容C结构体的用法
people p2;//C++中的类,people是类名
//函数调用
p1.init("张三",20);
p1.print();
return 0;
}
定义方式:
1.成员函数声明和定义都放在类中,需注意编译器可能会将其当成内联函数处理。
2.类的声明放在.h文件中,定义放在.cpp文件中,需注意指定类域。
二、类的访问限定符和封装
(1)访问限定符
访问限定符说明:
1. public修饰的成员在类外可以直接被访问。
2. protected和private修饰的成员在类外不能直接被访问。
3. 访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止。
4. class的默认访问权限为private,struct为public(因为struct要兼容C)。
class people {
private:
char _name[10];
int _age;
public:
void init(const char* name,int age)
{
strcpy(_name,name);
_age=age;
}
void print()
{
count<<_name<<endl;
count<<_age<<endl;,
}
};
(2)封装
封装的本质是一种更严格的管理,用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。隐藏对象的属性和实现细节,仅对外公开接口来和对象进行交互。
三、类的大小
class Stack
{
private:
int* a;
int _top;
int _capacity;
public:
void Init();
void Push(int);
void Pop();
}
上面这个类定义的对象大小为12个字节(需要用到C语言中结构体大小的计算,内存对齐的知识),它只包含了成员变量并未包含成员函数的大小。这是因为每个对象中都有独立的成员变量,而成员函数并不是对象特有的,为避免空间浪费将成员函数放到了公共代码段。所以计算类或类对象的大小只看成员变量,还要考虑内存对齐(与C语言一致)。需要注意的是,当类中无成员变量或为空类时,类的大小为1字节。这一字节不存储有效数据,可以想象为占位,表示对象存在。
四、this指针
class Stack
{
public:
int* a;
int _top;
int _capacity;
void Init();
void Push(int);
void Pop();
}
int main()
{
Stack s1;
s1._top;
S1.Init();
return 0;
}
以上代码中的s1._top与s1.Init()有着不同的意义,s1._top的意义为到对象空间内中找到_top的空间,s1.Init()的意义并不是到对象中找到Init函数地址,成员函数地址并没有存放在对象中而是存放在公共代码区。为了区分不同对象调用的成员函数,成员函数会被处理增加对象的指针的参数,这个指针就是this指针。s1.Init()隐藏了指向s1对象空间的this指针,成员函数void Init()也隐藏了指向对象空间this形参。
this指针特性:
1.成员函数定义内可以使用this指针,但它被const修饰不能被改变。
2.this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参。所以对象中不存储this指针。
3.this指针是成员函数第一个隐含的指针形参,一般情况是存放在栈,有些编译器存放在寄存器。
为了加深对this指针的理解我们来看个程序:
程序一:
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
void Show()
{
cout<<"Show()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->Show();
}
程序二:
class A
{
public:
void PrintA()
{
cout<<_a<<endl;
}
void Show()
{
cout<<"Show()"<<endl;
}
private:
int _a;
};
int main()
{
A* p = nullptr;
p->PrintA();
}
结果:程序一正常运行,程序二崩溃。分析:p虽然是空指针,但是p调用成员函数不会编译报错(这并不是一个语法错误),因为成员函数没有在对象内所以p调用成员函数不会出现空指针访问,这里会把p作为实参传递给隐藏的this指针。程序一中并没有对this指针解引用,程序二使用了this指针(这里为空)访问成员变量所以崩溃了。