文章目录
前言
类和对象是基于面向对象的语言的精髓所在,之前的C语言是面向过程的,关注的是过程,分析出求解问题的步骤,通过函数调用逐步解决问题。而面向对象,关注的是对象,将一件件事情拆分成不同的对象,靠对象之间交互完成
一、类
C语言中,结构体中只能定义变量,在C++中,结构体内不仅可以定义变量,也可以定义函数
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;
s.SetStudentInfo("zhangsan", "man", 20);
s.PrintStudentInfo();
return 0;
}
上面结构体的定义,在C++中更喜欢用class来代替
二、类的定义
class classname
{
//类体:由成员函数和成员变量组成
}; //注意这里有分号
class为定义类的关键字,classname为类的名字,{}中为类的主体,注意类定义结束时后面又分号
类的两种定义方式:
1.声明和定义全部放在类中,需要注意:成员函数如果在类中定义,编译器可能会将其当成内联函数处理
class classname
{
public:
//成员函数
private:
//成员变量
};
2.声明放在.h文件种,类的定义放在.cpp文件中
三、类的访问限定符及封装
3.1 访问限定符
C++实现封装的方式:用类将对象的属性与方法结合在一块,让对象更加完善,通过访问权限选择性的将其接口提供给外部的用户使用。
1.public修饰的成员在类外可以直接被访问
2.protected和private修饰的成员在类外不能直接被访问
3.访问权限作用域从该访问限定符出现的位置开始直到下一个访问限定符出现时为止
4.class的默认访问权限为private,struct为public(因为struct要兼容C)
注意: 访问限定符只有在编译时有用,当数据映射到内存后,没有任何访问限定符上的区别
3.2 封装
封装:将数据和操作数据的方法进行有机结合,隐藏对象的属性和细节,仅对公开接口来和对象进行交互
扫描二维码关注公众号,回复: 15622917 查看本文章封装本质上是一种管理: 使用protected/private把成员封装起来。开放一些共有的成员函数对成员合理的访问。所以封装本质是一种管理
四、类的作用域
类定义一个新的作用域,类的所有成员都在类的作用域中。在类体外定义成员,需要使用::
作用域解析符指明成员属于哪个类域
class Person
{
public:
void PrintPersonInfo();
private:
char _name[20];
char _gender[3];
int _age;
};
// 这里需要指定PrintPersonInfo是属于Person这个类域
void Person::PrintPersonInfo()
{
cout<<_name<<" "_gender<<" "<<_age<<endl;
}
五、类的实例化
用类类型创建对象的过程,称为类的实例化
- 类只是一个模型一样的东西,限定了类有哪些成员,定义出一个类并没有分配实际的内存空间来存储它
- 一个类可以实例化出多个对象,实例化的对象占用实际的物理空间,存储类成员变量
class Person
{
public:
Person(const char* name, const char* sex ,int age)
:_name(name)
,_sex(sex)
,_age(age)
{
}
void showInfor()
{
cout << _name << "-" << _sex << "-" << _age << endl;
}
private:
const char* _name;
const char* _sex;
int _age;
};
int main()
{
Person p1("zhangsan", "man", 20);
p1.showInfor();
Person p2("lisi", "woman", 15);
p2.showInfor();
return 0;
}
这就是一个类实例化出了完全不同的两个对象p1和p2
六、类对象模型
6.1 计算类对象的大小
对于类对象而言,每个对象的成员变量是互相独立的,但是调用的成员函数是同一个,若是成员函数也是独立的,每次类的实例化相同的代码会保存多次,会产生空间浪费。
所以对类对象只保存成员变量,成员函数存放在公共代码段
class Person
{
public:
Person(const char* name, const char* sex ,int age)
:_name(name)
,_sex(sex)
,_age(age)
{
}
void showInfor()
{
cout << _name << "-" << _sex << "-" << _age << endl;
}
private:
const char* _name;
const char* _sex;
int _age;
};
class A1 {
public:
void f1() {
}
private:
int _a;
};
class A2 {
public:
void f2() {
}
};
int main()
{
cout << sizeof(Person) << endl;
cout << sizeof(A1) << endl;
cout << sizeof(A2) << endl;
return 0;
}
结论: 一个类的大小,实际就是该类中“成员变量“之和,当然也要进行内存对齐,注意空类的大小,空类比较特殊,编译器给了空类一个字节来唯一标识这个类
七、this指针
7.1 this指针的概念
class Person
{
public:
Person(const char* name, const char* sex ,int age)
:_name(name)
,_sex(sex)
,_age(age)
{
}
void showInfor()
{
cout << _name << "-" << _sex << "-" << _age << endl;
}
private:
const char* _name;
const char* _sex;
int _age;
};
int main()
{
Person p1("zhangsan", "man", 20);
p1.showInfor();
Person p2("lisi", "woman", 15);
p2.showInfor();
return 0;
}
上述代码的Person类中有showInfo成员函数,函数体中没有关于不同对象的区分,那么p1调用showInfo函数时,该函数是如何知道应该设置p1对象,而不是设置p2对象呢?
C++中通过引入this指针解决该问题,即:C++编译器给每个”非静态的成员函数“增加了一个隐藏的指针参数,让该指针指向当前对象(函数运行时调用该函数的对象),在函数体中所有成员变量的操作,都是通过该指针去访问。只不过所有的操作对用户都是透明的,即用户不需要来传递,编译器自动完成
7.2 this指针的特性
- this指针的类型:类类型* const
- 只能在”成员函数“的内部使用
- this指针本质上其实是一个成员函数的形参,是对象调用成员函数时,将对象地址作为实参传递给this形参,所以对象中不存储this指针
- this指针是成员函数第一个隐含的指针形参,一般情况由编译器通过ecx寄存器自动传参,不需要用户传递
class A
{
public:
void PrintA()
{
cout << _a << endl;
}
void Show()
{
cout << "Show()" << endl;
}
private:
int _a;
};
int main()
{
A* p = NULL;
p->PrintA(); //error 这里是对空指针的引用
p->Show();
}