C++基础学习---> 类的基础
类属性成员的访问权限
公共权限:类内可以访问,类外可以访问
保护权限:类内可以访问,类外不可以访问 继承中,子类可以访问父类的成员
私有权限:类内可以访问,类外不可以访问 继承中,子类不可以访问父类的成员
保护权限和私有权限的区别就是在继承中子类是否可以访问父类的成员
class Person
{
public:
string name;
protected:
string car;
private:
string password;
public:
void func()
{
//类内访问
name = "111";
car = "222";
password = "123";
}
}
int main()
{
Person p1;
p1.car = "333"; //error 类外不能访问
}
class和struct的区别
参考这个大佬的博客
struct是一种数据结构,而class是一个对象,如果需求中的数据需要去解析之类的工作,我还是习惯用struct,如果这个数据有很多属性、行为更适合用class,比如说解析 GPS的0183格式的数据,这个时候用struct看起来是比较方便点
class和struct没有多大的区别,其实最主要的就是默认属性的问题
自身中:struct默认属性是public的,而class默认的属性是private的
继承中:struct默认是public的,而class是private,但是在继承中,出于规范而言,我是建议无论是什么继承,最好就是指明继承的方式,而不是默认继承。
对象的初始化和清理
构造函数
一个对象或者变量没有初始状态,对其使用后果是未知
同样的使用完一个对象或变量, 没有及时清理,也会造成一定的安全问题
构造函数和析构函数解决上述问题,这两个函数将会被编译器自动调用,完成对象初始化和
对象的初始化和清理工作是编译器强制要做的事情,如果我们不提供构造和析构,编译器会提供
编译器提供的构造函数和析构函数是空实现。
●构造函数:主要作用在于创建对象时为对象的成员属性赋值,
●析构函数:主要作用在于对象销毁前系统自动调用,执行一 -些清理工作。
构造函数语法:类名(){}
构造函数没有返回值也不写void
函数名与类名一致
构造函数可以有参数,因此可以发生重载
程序在调用对象的时候会自动调用构造,无需手动调用,并且只调用一次
构造函数的分类:
按参数: 有参构造 无参构造(默认构造)
按类型:普通构造 拷贝构造
拷贝构造:将一个已经实例化的对象做为参数传入,将一些属性赋值给新的对象
const Person &p (常量引用参数)
调用:
括号法:
Person p1; //默认构造函数不用加括号
Person p2(10);
Person p3(p2);//拷贝构造函数
显示法:
Person p1; //默认构造函数不用加括号
Person p2 = Person(10);
Person p3 = Person(p2);//拷贝构造函数
Person(10); //匿名对象 特点:当前结束结束之后,系统立即回收,即执行析构函数
注意:
不要使用拷贝构造函数创建一个匿名对象 —> Person p1; Person(p1);
隐式转化法:
Person p1 = 10; //等价于 Person p1 = Person(10);
Person p1 = p2; //拷贝构造
拷贝构造函数使用的地方:
1.使用一个已经创建完毕的对象来初始化一个新的对象
2.值传递的方式给函数参数传值
3.值方式返回局部变量
调用原则:
编译器至少提供的函数:
1.默认构造函数(无参,函数体为空)
2.默认析构函数(无参,函数体为空)
3.默认拷贝构造函敌,对属性进行值拷贝
●如果用户定义有参构造函数,Cc+不在提供默认无参构造,但是会提供默认拷贝构造
●如果用户定义拷贝构造函数,C++不会再提供其他构造函数
深拷贝和浅拷贝 ***
浅拷贝:简单的赋值拷贝操作 出现的问题:内存重复释放
深拷贝:自己在堆区开一片内存进行拷贝,用完之后执行自己的析构函数进行清除
如果属性有在堆区开辟的,一定要自己提供拷贝构造函数,防止浅拷贝带来的问题
初始化列表:–>初始化属性
语法:构造函数():属性1(值1),属性2(值3),属性3(值3)…
{
}
析构函数
析构函数语法:~类名(){}
析构函数没有返回值也不用写void
函数名与类名一致,在名字前面要加~
西沟函数不可以带参数,因此不可以发生重载
程序在对象销毁前自动调用析构函数,无需手动调用,并且只调用一次
class Person()
{
//构造参数
Person()
{
}
//·析构函数
~Person()
{
}
}
(划重点)类对象作为类成员:构造时先构造类对象,在构造自身,析构顺序与构造相反
class A()
class B()
{
A a;
}
class Phone
{
public:
Phone(string name)
{
m_Phone_name = name;
cout << "Phone对象的构造" << endl;
}
~Phone()
{
cout << "Phone对象的析构" << endl;
}
string m_Phone_name;
}
class Person
{
public:
Person(string name,string pname):m_Name(name),m_pName(pname)
{
cout << "Person对象的构造" << endl;
}
~Person()
{
cout << "Person对象的析构" << endl;
}
string m_Name;
Phone m_pName; //类对象作为类成员 创建
}
void test01()
{
Person p("张三","华为");
}
int main()
{
test01();
}
类的静态属性和成员函数
静态成员:static
->所有对象共享一份数据
->在编译阶段分配内存
->类内声明,类外初始化
静态成员函数
->所有对象共享一个函数
->静态成员函数只能访问静态成员变量
->静态成员函数也有访问权限
class Person
{
public:
static void func()
{
m_A = 100;
cout << "static void func 静态成员函数的调用" << endl;
}
static int m_A;
int m_B;
};
int Person::m_A = 0;
void test01()
{
//1.通过对象访问 func
//Person p;
//p.func();
//2.通过类名访问 func
Person::func();
}
int main()
{
test01();
}
成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上
class Person
{
//非静态成员变量,影响类所占空间大小
int m_A;
//静态成员变量,不影响类所占空间大小
static int m_B;
//非静态成员函数,不影响类所占空间大小
int func1() {}
//静态成员函数,不影响类所占空间大小
static int func2() {}
};
int Person::m_B = 0; //类内声明,类外初始化
void test01()
{
Person p;
//空对象占用内存空间为一个字节
//C++编译器会给每个空对象分配一个字节空间,是为了区分空对象占内存的位置,防止地址重复
cout << "size of p = " << sizeof(p) << endl;
}
int main()
{
test01();
}