1.封装
1.1语法:class 类名{ 访问权限:属性 / 行为};
意义:将属性和行为放到一起来表现事物。
设计一个圆类,求圆的周长。
#include <iostream>
using namespace std;
//圆周率
const double PI = 3.14;
//创造一个圆类,求圆的周长。
class circle {
//访问权限,公共权限
public:
//属性,周长
int c_r = 0;
//行为(一般用函数来表示)
double zhouchang()
{
return 2 * PI * c_r;
}
};
int main() {
//通过圆类创造一个具体的圆
circle c1; //创造了圆c1;
c1.c_r = 10;
cout << "圆的周长是" << c1.zhouchang() << endl;
system("pause");
return 0;
}
1.2访问权限
公共权限:public,类内可以访问,类外也可以访问
保护权限:protected,类内可以访问,类外不可以访问
私有权限:private,类内可以访问,类外不可以访问
保护权限和私有权限的区别主要在于继承方面,
保护权限下子类可以访问父类
私有权限下子类不可以访问父类
1.3struct与class的区别在于默认权限不同,其他没有什么区别
struct的默认权限是公共权限 public
class的默认权限是私有权限private
1.4成员属性私有化
优点1:将所有成员属性设置为私有,可以控制自己的读写权限
优点2:对于写权限可以检测出数据的有效性
#include <iostream>
using namespace std;
#include <string>
//设置人类
class Person {
public:
void set_name(string name)
{
P_name = name;
}
void getname()
{
cout << "这个人的名字是:" << P_name << endl;
}
void setage(int age)
{
P_age = age;
}
void getage()
{
cout << "这个人的年龄是:" << P_age << endl;
}
void setlover(string lover)
{
P_lover = lover;
}
void getlover()
{
cout << "这个人的爱人是:" << P_lover << endl;
}
private: //所有的属性都是私有权限,类外无法访问,因此如果要给属性赋值,则需要一些赋值的接口。
string P_name;
int P_age;
string P_lover;
};
int main() {
Person p1;
p1.set_name("张三");
p1.setlover("李四");
p1.setage(22);
p1.getage();
p1.getlover();
p1.getname();
system("pause");
return 0;
}
2.对象的特性
2.1构造函数与析构函数
构造函数:主要在于创造对象时为对象的成员属性赋值,构造函数由编译器自动调用无需手动调用
析构函数:主要作用于对象销毁前系统自动调用,执行一些清理工作。
如果我们不提供构造函数与析构函数,那么编译器会自动提供,但构造和析构都是空实现。
构造函数的语法 类名(){}
1.构造函数没有返回值也不写void
2.函数名与类名相同
3.构造函数可以有参数,因此可以发生重载
4.程序在调用对象时会自动调用构造,无需手动调用,且只会调用一次。
2.2析构函数的语法 ~类名 () {}
1.析构函数没有返回值也不写void
2.函数名称与类名相同
3.析构函数不可以有参数,因此不能发生重载
4.在对象销毁前会自动调用析构,无需手动调用,且只会调用一次。
2.3构造函数的分类与调用
1.按照参数分类:有参构造和无参构造
2.按照类型分类:普通构造和拷贝构造
三种调用方式:
1.括号法 2.显示法 3.隐式转化法
#include <iostream>
using namespace std;
class Person
{
public:
Person() //无参构造
{
cout << "构造函数的无参调用" << endl;
}
Person(int a) //有参构造
{
age = a;
cout << "构造函数的有参构造" << endl;
}
//按照类型分以上统称为普通构造
Person(const Person& p) //拷贝构造
{
age = p.age; //拷贝函数可以将传入对象上面的所有属性传到自己身上
cout << "构造函数的拷贝构造" << endl;
}
int age; //Person上面的属性
};
//调用
void test01()
{
//1.括号法
Person p1; //调用无参构造
Person p2(10); // 调用有参构造
Person p3(p2); //调用拷贝构造
//注意事项:在调用无参构造(默认构造)时不要加()即Personp1(),,,
//因为这样编译器会将其看做成函数的声明,直接Person p1即可
//2.显示法
Person p1;
Person p2 = Person(10); //有参构造
Person p3 = Person(p2); //拷贝构造
//Person(10) 匿名对象 特点:当前执行结束后,系统会自动回收匿名对象
//注意事项
//不要利用拷贝构造函数初始化匿名对象,编译器会认为Person(p3) ==== Person p3;重复定义
//3.隐式转化分法
Person p4 = 10; //有参构造
Person p5 = p4; //拷贝构造
}
int main() {
test01();
system("pause");
return 0;
}
2.4拷贝构造函数的调用时机
1.使用一个已经创建完毕的对象来初始化一个新的对象
2.值传递的方式给函数参数传值
3.以值传递的方式返回局部对象
#include <iostream>
using namespace std;
class Person
{
public:
Person()
{
cout << "Person无参构造的调用" << endl;
}
Person(int a)
{
age = a;
cout << "Person有参构造的调用" << endl;
}
Person(const Person& p)
{
age = p.age;
cout << "Person拷贝函数的调用" << endl;
}
~Person()
{
cout << "Person析构函数的调用" << endl;
}
int age;
};
//1.使用一个创建完毕的对象来初始化一个新对象
void test01()
{
Person p1(10);
Person p2(p1);
cout << "p2的年龄" << p2.age << endl;
}
//2.以值传递的方式给函数参数传值
void dowork(Person p)
{
}
void test02()
{
Person p;
dowork(p); //在进行值传递的时候编译器会制造出一个临时的副本,此时会调用拷贝构造函数
}
//3.以值传递的方式返回局部对象
Person dowork02()
{
Person p1;
return p1;
}
void test03()
{
Person p2 = dowork02();
}
int main() {
//test01();
test02();
system("pause");
return 0;
}
2.5构造函数的调用规则
默认情况下,C++编译器至少给一个类添加3个函数
①默认构造函数(无参,函数体为空)
②默认析构函数(无参,函数体为空)
③默认拷贝构造函数(对属性进行值拷贝)
构造函数的调用规则如下:
如果用户提供有参构造函数,则编译器将不再提供默认无参构造函数,但会提供默认拷贝构造函数
如果用户定义了拷贝构造函数,C++将不会提供其他构造函数。