类和对象---静态成员
静态成员就是在成员变量和成员函数前加上关键字static,称为静态成员
静态成员分为:
一、静态成员变量
1.所有对象共享一份数据
2.在编译阶段分配内存,全局区
3.类内声明,类外初始化
静态成员变量不属于某个对象上,所有对象都共享同一份数据,因此静态成员变量有两种访问方式:
①通过对象进行访问
②通过类名进行访问
静态成员变量同样具有访问权限,注意声明作用域。
#include<iostream>
#include<string>
using namespace std;
class A
{
public:
//所有对象公用一份数据
//编译阶段就分配内存
//类内申明 类外初始化操作
static int m_a; //类内声明
private:
static int m_b;
};
//类外初始化 加上A类的作用域 " A:: "
int A::m_a = 100;
void test()
{
A a;
cout << a.m_a << endl;
A b;
b.m_a = 200;
cout << a.m_a << endl;
}
//访问方式
void test11()
{
//通过对象进行访问
A a;
cout << a.m_a << endl;
//通过类名进行访问
cout << A::m_a << endl;
//cout << A::m_b << endl; 不可访问!
}
int main()
{
//test();
test11();
return 0;
}
二、静态成员函数
1.所有对象共享一个函数
访问方式:
①通过对象进行访问
②通过类名进行访问
2.静态成员函数只能访问静态成员变量
①静态成员函数可以访问静态成员变量
②静态成员函数不可以访问非静态成员变量,因为无法区分是哪个对象的成员变量
静态成员函数同样具有访问权限,注意声明作用域。
#include<iostream>
#include<string>
using namespace std;
class B
{
public:
static int m_b;
int m_a;
//静态成员函数
static void func()
{
m_b = 100; //静态成员函数可以访问静态成员变量
//m_a = 200;//静态成员函数不可以访问非静态成员变量
cout << "static void func 的调用" << endl;
}
private:
void func2()
{
cout << "static void func2 的调用" << endl;
}
};
int B::m_b = 0;
void test()
{
//通过对象访问
B a;
a.func();
//通过类名访问
B::func();
//B::func2() //不可调用 因为属于private访问权限
}
int main()
{
test();
return 0;
}
C++对象模型和this指针
一、c++成员变量和成员函数分开存储
在c++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上,与静态成员变量,静态成员函数,非静态成员变量分开存储。
空对象占用内存为1 c++编译器会给每个空对象分配一个字节,是为了区分空对象占用内存的位置,每个空对象也应该有一个独一无二的内存地址。
class Person
{
};
void test0201()
{
Person p;
cout << "size of p = " << sizeof(p) << endl; //空对象占用内存为1 c++编译器会给每个空对象分配一个字节,是为了区分空对象占用内存的位置
}
非静态成员变量属于类的对象上
class Person
{
int m_a;//非静态成员变量
};
void test0202()
{
Person p;
cout << "size of p = " << sizeof(p) << endl; // 4字节 说明非静态成员变量属于类内内存空间
}
静态成员变量不属于类的对象上
class Person
{
int m_a;//非静态成员变量
static int m_b;
};
int Person::m_b = 10;
void test0202()
{
Person p;
cout << "size of p = " << sizeof(p) << endl; // 4字节 说明静态成员变量不属于类的对象上
}
非静态成员函数不属于类的对象上
class Person
{
int m_a;//非静态成员变量
static int m_b;
void func(){}//非静态成员函数
};
void test0202()
{
Person p;
cout << "size of p = " << sizeof(p) << endl; // 4字节 说明非静态成员函数不属于类的对象上
}
静态成员函数不属于类的对象上
class Person
{
int m_a;//非静态成员变量
static int m_b;
void func(){}//非静态成员函数
static void func2(){}//静态成员函数
};
void test0202()
{
Person p;
cout << "size of p = " << sizeof(p) << endl; // 4字节 说明静态成员函数不属于类的对象上
}
二、this指针概念
通过前面的学习我们知道,在c++中成员变量和成员函数是分开存储的,而每一个非静态成员函数只会诞生一个实例,也就是说多个同类型的对象会公用一块代码,那么问题是:这一块代码是如何区分哪个对象调用的自己呢?
c++提供的特殊对象指针,this指针,解决上述问题,this指针指向被调用的成员函数所属的对象,this指针是隐含在每一个非静态成员函数内的一种指针,this指针不需要定义,直接使用即可。
用处1 解决名称冲突
错误用法
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age)
{
age = age;//同名 会混淆
}
int age;
};
void test0301()
{
Person p(18);
cout << "年龄为: " << p.age << endl;
}
int main()
{
test0301();
return 0;
}
this指针用法
class Person
{
public:
Person(int age)
{
//this指针指向的是被调用的成员函数所属的对象
this->age = age;
}
int age;
};
用处2 返回对象本身用*this
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
Person(int age)
{
//this指针指向的是被调用的成员函数所属的对象
this->age = age;
}
Person& personadd(Person& p)
{
this->age += p.age;
return *this;//*this指针返回对象本身
}
int age;
};
void test0301()
{
Person p(18);
cout << "年龄为: " << p.age << endl;
Person p1(10);
p1.personadd(p).personadd(p).personadd(p).personadd(p);
cout << "p1的年龄为:" << p1.age << endl;
}
int main()
{
test0301();
return 0;
}
三、空指针访问成员函数
c++中空指针也能调用成员函数,但是要注意有没有用到this指针,如果用到this指针,需要加以判断保证代码健壮性。
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
void showclass()
{
cout << "this is Person class" << endl;
}
void showPersonAge()
{
if (this == NULL)
{
return;
}
cout << "age = " << m_age << endl;
}
int m_age;
};
void test0501()
{
Person * p = NULL;
p->showclass(); //可以运行
p->showPersonAge(); //不可运行 空指针不可访问属性
}
int main()
{
test0501();
return 0;
}
四、const修饰成员函数
常函数
成员函数后加const后我们称这个函数为常函数
常函数内不可修改成员属性
成员属性声明时加关键字mutable,在常函数中仍可以修改
常对象
声明对象前加const称该对象为常对象
常对象只能调用常函数
#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
//this 指针的本质是指针常量 指针的指向是不可以修改的
//在成员函数后加const,修饰的是this指向,让指针指向的值也不可修改
void showPerson() const
{
//this->m_a = 100; 报错
this->m_b = 100; //不报错
}
void func()
{
}
int m_a;
mutable int m_b;
};
//常对象
void test0601()
{
const Person p;
//p.m_a = 100; //报错
p.m_b = 100; //未报错
//常对象只能调用常函数
p.showPerson(); //未报错
//p.func(); 报错 预防修改属性
}
int main()
{
test0601();
return 0;
}