#include
using namespace std;
// 成员变量 和 成员函数 分开存储
// 只有非静态成员变量才属于类的对象上,其他都是独一份
// 空对象
class Person
{
};
void test01()
{
// C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
// 每个空对象也应该有个独一无二的内存地址
Person p;
// 空对象占用的内存空间为: 1
cout << "size of p=" << sizeof(p) << endl;
}
int main()
{
test01();//1个字节
system("pause");
return 0;
}
#include
using namespace std;
// 成员变量 和 成员函数 分开存储
// 只有非静态成员变量才属于类的对象上,其他都是独一份
class Person
{
int m_A;// 非静态成员变量,属于类的对象上
static int m_B;// 静态成员变量 —— 需要类内声明,类外初始化,不属于类的对象上
void func() {} // 非静态成员函数,不属于类的对象上
static void func2() {}// 静态成员函数,不属于类的对象上
};
int Person::m_B = 10;
void test01() // 空对象,class里面没有内容
{
// C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
// 每个空对象也应该有个独一无二的内存地址
Person p;
// 空对象占用的内存空间为: 1
cout << "size of p = " << sizeof(p) << endl;
}
void test02()
{
Person p1;// 此时不是空对象
cout << "size of p1 =" << sizeof(p1) << endl;// 4个字节
}
int main()
{
test01();//1个字节
test02();//4个字节
system("pause");
return 0;
}
通过上面我们知道在C++中成员变量和成员函数是分开存储的,每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码。
问题是:这一块代码是如何区分那个对象调用自己的呢?就是说 假设只有一个函数,有很多的对象p1,p2,p3都在使用这个函数,在函数体内部如何区分是p1调的还是p2调的,修改属性
this指针的用途:
this指针的本质 是指针常量 指针的指向是不可以修改的
方法1:使用m_,区分和形参的名称
public:
Person(int age)//这是形参age
{
m_age = age; // 成员member,后面需要
}
int m_age;
方法2:使用this指针(推荐)
public:
Person(int age)//这是形参age
{
//this指针指向 被调用成员函数 所属的对象
//this指的是成员属性age,后面是形参age
this->age = age;
}
int age;
Person& PersonAddAge2(Person &p)// 第2个Person&表示以引用的方式传入
{
this->age += p.age;// 将别人的年龄加到自身上面
// this指向p2的指针,*this指向的就是p2这个对象的本体
return *this;// 要返回本体,要用引用的方式返回,不能只用值返回Person
}
Person PersonAddAge2(Person &p)// 第2个Person&表示以引用的方式传入
{
this->age += p.age;// 将别人的年龄加到自身上面
// this指向p2的指针,*this指向的就是p2这个对象的本体
return *this;// 要返回本体,要用引用的方式返回,不能只用值返回Person
// 如果开头Person&变成Person的话,就会变成值传递
}

if (this == NULL)
{
return;
}
#include
using namespace std;
//空指针调用成员函数
class Person
{
public:
void showClassName()
{
cout << "this is Person class" << endl;
}
void showPersonName()
{
// 报错的原因是传入的指针为空NULL,没法无中生有
if (this == NULL)
{
return;
}
// 属性的前面都默认加入了this指针,this是个空值,没有确定的对象
cout << "age = " << this->m_Age << endl;// 属性默认加this
}
int m_Age;
};
void test01()
{
Person* p = NULL;
p->showClassName();
p->showPersonName();
Person p1;
p1.showClassName();
p1.showPersonName();
}
int main()
{
test01();
system("pause");
return 0;
}
this指针 —— 指针常量,不加const指向的值可以修改
// 常函数 —— 成员函数后加const,常函数内不可以修改成员属性
class Person
{
public:
// this指针的本质 是指针常量 指针的指向是不可以修改的
// const Person * const this
// 前面const限制指针的值不可以修改,后面const限制指针的指向不可以修改
// 在成员函数后面加const,修饰的是this指针,让指针指向的值也不可以修改
void showPerson() const //加入const后,属性值就不可以修改
{
this->m_B = 100;
// this->m_A = 100;
// this = NULL;
//this指针不可以修改指针的指向,若要指针指向的值也不可以修改,函数后面加const
}
//普通函数
void func() {}
int m_A;
//特殊变量,即使在常函数和常对象中,也可以修改这个值。加上关键字mutable,m_B可以修改值
mutable int m_B;
};
常对象:
void test02()
{
const Person p;// 在对象前加const,变为常对象
// p.m_A = 100;// 对象属性不可以修改(报错)
p.m_B = 100;// m_B是特殊值,在常对象下也可以修改(加上mutable)
// 常对象只能调用常函数
p.showPerson();
// p.func();// 常对象不可以调用普通的成员函数,因为普通成员函数可以修改属性
}
总程序
#include
using namespace std;
// 常函数 —— 成员函数后加const,常函数内不可以修改成员属性
class Person
{
public:
// this指针的本质 是指针常量 指针的指向是不可以修改的
// const Person * const this
// 前面const限制指针的值不可以修改,后面const限制指针的指向不可以修改
// 在成员函数后面加const,修饰的是this指针,让指针指向的值也不可以修改
void showPerson() const //加入const后,属性值就不可以修改
{
this->m_B = 100;
// this->m_A = 100;
// this = NULL;
//this指针不可以修改指针的指向,若要指针指向的值也不可以修改,函数后面加const
}
//普通函数
void func() {}
int m_A;
//特殊变量,即使在常函数和常对象中,也可以修改这个值。加上关键字mutable,m_B可以修改值
mutable int m_B;
};
void test01()
{
Person p;
p.showPerson();
}
//常对象
void test02()
{
const Person p;// 在对象前加const,变为常对象
// p.m_A = 100;// 对象属性不可以修改(报错)
p.m_B = 100;// m_B是特殊值,在常对象下也可以修改(加上mutable)
// 常对象只能调用常函数
p.showPerson();
// p.func();// 常对象不可以调用普通的成员函数,因为普通成员函数可以修改属性
}
int main()
{
system("pause");
return 0;
}
生活中你的家有客厅(Public),有你的卧室(Private),客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去,但是你也可以允许你的好闺蜜好基友进去。
在程序里,有些私有属性,想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术,友元的目的就是让一个函数或者类 访问另一个类中私有成员,友元的关键字为 friend
#include
#include
using namespace std;
// 建筑物类
class Building
{
// goodgay全局函数 是 Building好朋友,可以访问 Building 找那个私有成员
friend void goodGay(Building* building);
public:
// 无参构造函数
Building()
{
// 赋初值
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
public:
string m_SittingRoom;// 客厅
private:
string m_BedRoom;// 卧室
};
// 全局函数 - 好朋友 访问私有成员
void goodGay(Building* building) // 传入指针Building(引用也可以)
{
cout << "好基友的全局函数 正在访问:" << building->m_SittingRoom << endl;// 公共属性
cout << "好基友的全局函数 正在访问:" << building->m_BedRoom << endl;// 私有属性
}
void test01()
{
Building building1;// 实例化Building对象
goodGay(&building1);// 以指针的形式(传入地址)将对象传入全局函数
}
int main()
{
test01();
system("pause");
return 0;
}
class Building
{
public:
// 无参构造函数
Building();
public:
string m_SittingRoom;// 客厅
private:
string m_BedRoom;// 卧室
};
// 类外写成员函数
Building::Building() // 类中的成员函数,Building下面的构造函数Building
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
步骤:
#include
#include
using namespace std;
// 类做友元 —— 让一个类可以访问另一个类的私有成员
class Building;// 创建building,告诉编译器一会会写这个类
class GoodGay// 创建goodgay类
{
public:
// 无参构造函数
GoodGay();
// 参观函数 访问Building中的属性 公共和私有属性
void visit();
private:
Building* building;// 指针类型
};
class Building
{
// GoodGay类是本类的好朋友,可以访问本类的私有成员
friend class GoodGay;
public: // 赋初值
// 无参构造函数
Building();
public:
string m_SittingRoom;// 客厅
private:
string m_BedRoom;// 卧室
};
// 类外写成员函数
Building::Building() // 类中的成员函数,Building下面的构造函数Building,赋初值
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
GoodGay::GoodGay()
{
// 创建建筑物对象
building = new Building;
// new表示在堆区创建出一个对象,new什么样的类型,就返回什么样的指针
}
void GoodGay::visit()// goodgay下面的函数
{
cout << "好基友类正在访问:" << building->m_SittingRoom << endl;
cout << "好基友类正在访问:" << building->m_BedRoom << endl;
}
void test01()
{
GoodGay gg;// 创建goodGay对象,调用goodGay的构造函数
gg.visit();
}
int main()
{
test01();
system("pause");
return 0;
}

building1 = new Building;
// building指针等于new的Building对象
// 相当于在堆区创建一个Building对象,并且用指针维护这个建筑物对象
// 告诉编译器,GoodGay类下的visit1成员函数作为本类的好朋友,可以访问私有成员
friend void GoodGay::visit1();
// friend void GoodGay::visit2();// 没有这句的话visit2不可以访问私有成员,只能访问私有属性
#include
#include
using namespace std;
class Building;// 首先声明Building类
class GoodGay
{
public:
// 无参构造函数
GoodGay();
// 用类外实现函数
void visit1();// 让visit函数可以访问Building中私有成员
void visit2();// 让visit2函数不可以访问Building中私有成员
Building* building1;
};
class Building
{
// 告诉编译器,GoodGay类下的visit1成员函数作为本类的好朋友,可以访问私有成员
friend void GoodGay::visit1();
// friend void GoodGay::visit2();// 没有这句的话visit2不可以访问私有成员
public:
Building();// 构造函数的声明
public:
string m_SittingRoom;// 客厅
private:
string m_BedRoom;// 客厅
};
// 类外实现成员函数
Building::Building()
{
m_SittingRoom = "客厅";
m_BedRoom = "卧室";
}
GoodGay::GoodGay()// 类外实现
{
building1 = new Building;
// building指针等于new的Building对象
// 相当于在堆区创建一个Building对象,并且用指针维护这个建筑物对象
}
void GoodGay::visit1()
{
cout << "visit1 函数正在访问:" << building1->m_SittingRoom << endl;
cout << "visit1 函数正在访问:" << building1->m_BedRoom << endl;
}
void GoodGay::visit2()
{
cout << "visit2 函数正在访问:" << building1->m_SittingRoom << endl;
// cout << "visit2函数正在访问:" << building1->m_BedRoom << endl;
// 成员函数不做友元,不能访问私有成员
}
void test01()
{
GoodGay gg;
gg.visit1();
gg.visit2();
}
int main()
{
test01();
system("pause");
return 0;
}
