3. C++对象模型和this指针
3.1 成员变量和成员函数分开存储
在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上。
#include<iostream>
using namespace std;
class person
{
int m_a;
static int m_b;
void func() {}
static void func2() {}
};
int person::m_b = 10;
void test01()
{
person p;
cout << "size of p=="<<sizeof(p) << endl;
}
void test02()
{
person p;
cout << "size of p==" << sizeof(p) << endl;
}
int main() {
test02();
system("pause");
return 0;
}
3.2 this指针概念
我们知道在C++中成员变量和成员函数是分开存储的 每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码那么问题是:这—块代码是如何区分那个对象调用自己的呢? C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象 this指针是隐含每一个非静态成员函数内的—种指针 this指针不需要定义,直接使用即可 this指针的用途:·当形参和成员变量同名时,可用this指针来区分 ·在类的非静态成员函数中返回对象本身,可使用return *this
#include<iostream>
using namespace std;
class person
{
public:
person(int age)
{
this->age = age;
}
person &personaddage(person& p)
{
this->age += age;
return *this;
}
int age;
};
void test01()
{
person p1(18);
cout << "p1的年龄" <<p1.age<< endl;
}
void test02()
{
person p1(18);
person p2(18);
p2.personaddage(p1).personaddage(p1).personaddage(p1);
cout << "p2的年龄" << p2.age << endl;
}
int main() {
test02();
system("pause");
return 0;
}
3.3 空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针 如果用到this指针,需要加以判断保证代码的健壮性
#include<iostream>
using namespace std;
class person
{
public:
void showclassname()
{
cout << "this is person class" << endl;
}
void showpersonage()
{
if (this == NULL)
{
return;
}
cout<<"age=" <<m_age<< endl;
}
int m_age;
};
void test01()
{
person* p =NULL;
p->showclassname();
p->showpersonage();
}
int main() {
test01();
system("pause");
return 0;
}
3.4 const修饰成员函数
常函数 | 常对象 |
---|
成员函数后加const后我们称为这个函数为常函数 | 声明对象前加const称该对象为常对象 | 常函数内不可以修改成员属性 | 常对象只能调用常函数 | 成员属性声明时加关键字mutable后,在常函数中依然可以修改 | |
#include<iostream>
using namespace std;
class person
{
public:
void showperson() const
{
this->m_b = 100;
}
int m_a;
mutable int m_b;
};
void test01()
{
person p;
p.showperson();
cout << "good baby" << endl;
}
void test02()
{
const person p2;
p2.m_b = 100;
}
int main() {
test01();
system("pause");
return 0;
}
4.友元
生活中你的家有客厅(Public),有你的卧室(Private) 客厅所有来的客人都可以进去,但是你的卧室是私有的,也就是说只有你能进去但是呢,你也可以允许你的好闺蜜好基友进去。 在程序里,有些私有属性也想让类外特殊的一些函数或者类进行访问,就需要用到友元的技术 友元的目的就是让一个函数或者类访问另—个类中私有成员 友元的关键字为friend 友元的三种实现: .全局函数做友元 ·类做友元 ·成员函数做友元
4.1全局函数做友元
#include<iostream>
using namespace std;
class building
{
friend void goodgay(building* building);
public:
building()
{
m_sittingroom = "客厅";
m_bedroom = "卧室";
}
public:
string m_sittingroom;
private:
string m_bedroom;
};
void goodgay(building *b)
{
cout <<"好基友全局函数 正在访问" <<b->m_sittingroom <<endl;
cout << "好基友全局函数 正在访问" << b->m_bedroom << endl;
}
void test01()
{
building b2;
goodgay(&b2);
}
int main() {
test01();
system("pause");
return 0;
}
4.2类做友元
#include<iostream>
using namespace std;
class Building;
class goodgay
{
public:
goodgay();
void visit();
Building * building;
private:
};
class Building
{
friend class goodgay;
public:
Building();
public:
string m_sittingroom;
private:
string m_bedroom;
};
Building::Building()
{
m_sittingroom = "客厅";
m_bedroom = "卧室";
}
goodgay::goodgay()
{
building = new Building;
}
void goodgay::visit()
{
cout<<"好基友正在访问:" <<building->m_sittingroom << endl;
cout << "好基友正在访问:" << building->m_bedroom << endl;
}
void test01()
{
goodgay gg;
gg.visit();
}
int main() {
test01();
system("pause");
return 0;
}
4.3成员函数做友元
#include<iostream>
using namespace std;
class Building;
class goodgay
{
public:
goodgay();
void visit();
void visit2();
Building* building;
};
class Building
{
friend void goodgay::visit();
public:
Building();
public:
string m_sittingroom;
private:
string m_bedroom;
};
Building::Building()
{
m_sittingroom = "客厅";
m_bedroom = "卧室";
}
goodgay::goodgay()
{
building = new Building;
}
void goodgay::visit()
{
cout << "visit函数正在访问:" << building->m_sittingroom << endl;
cout << "visit函数正在访问:" << building->m_bedroom << endl;
}
void goodgay::visit2()
{
cout << "visit2函数正在访问:" << building->m_sittingroom << endl;
}
void test01()
{
goodgay gg;
gg.visit();
gg.visit2();
}
int main() {
test01();
system("pause");
return 0;
}
5运算符重载
5.1加号运算符重载
三种重载方法!
#include<iostream>
using namespace std;
class person
{
public:
person operator+(person & p)
{
person temp;
temp.m_a = this->m_a + p.m_a;
temp.m_b = this->m_b + p.m_b;
return temp;
}
int m_a;
int m_b;
};
person operator+(person& p1, person& p2)
{
person temp;
temp.m_a = p1.m_a + p2.m_a;
temp.m_b = p1.m_b + p2.m_b;
return temp;
}
person operator+(person& p1, int num)
{
person temp;
temp.m_a = p1.m_a + num;
temp.m_b = p1.m_b + num;
return temp;
}
void test01()
{
person p1;
p1.m_a = 10;
p1.m_b = 10;
person p2;
p2.m_a = 10;
p2.m_b = 10;
person p3 = p1.operator+(p2);
person p3 = operator+(p1, p2);
person p4 = p1 + 10;
cout <<"p3.m_a" << p3.m_a << endl;
cout <<"p3.m_b" << p3.m_b << endl;
cout << "p4.m_a" << p3.m_a << endl;
cout << "p4.m_b" << p3.m_b << endl;
}
int main() {
test01();
system("pause");
return 0;
}
5.2左移运算符重载
输出自定义数据类型
#include<iostream>
using namespace std;
class person
{
friend ostream& operator<<(ostream& cout, person p);
friend void test01();
public:
private:
int m_a;
int m_b;
};
ostream & operator<<(ostream& cout, person p)
{
cout << "m_a = " << p.m_a << "m_b = " << p.m_b;
return cout;
}
void test01()
{
person p;
p.m_a = 10;
p.m_b = 10;
cout << p<<endl;
}
int main() {
test01();
system("pause");
return 0;
}
5.3递增运算符重载
#include<iostream>
using namespace std;
class myinterger
{
friend ostream& operator<<(ostream& cout, myinterger myint);
public:
myinterger()
{
m_num = 0;
}
myinterger & operator++()
{
m_num++;
return *this;
}
myinterger operator++(int)
{
myinterger temp = *this;
m_num++;
return temp;
}
private:
int m_num;
};
ostream& operator<<(ostream& cout, myinterger myint)
{
cout << myint.m_num;
return cout;
}
void test01()
{
myinterger myint;
cout<<myint <<endl;
}
void test02()
{
myinterger myint;
cout << myint++ << endl;
cout << myint << endl;
}
int main() {
test02();
system("pause");
return 0;
}
5.4赋值运算符重载
#include<iostream>
using namespace std;
class person
{
public:
person(int age)
{
m_age = new int(age);
cout << "取" << endl;
cout << this->m_age << endl;
}
~person()
{
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
cout <<"析构" << endl;
}
}
person & operator=(person& p)
{
cout << this->m_age << endl;
if (m_age != NULL)
{
delete m_age;
m_age = NULL;
cout << "释放" << endl;
cout << this->m_age << endl;
}
m_age = new int(*p.m_age);
cout << this->m_age << endl;
return *this;
}
int* m_age;
};
void test01()
{
person p1(19);
person p2(20);
person p3(30);
p3 = p2 = p1;
cout << "p1的年龄为" << *p1.m_age << endl;
cout << "p2的年龄为" << *p2.m_age << endl;
cout << "p3的年龄为" << *p3.m_age << endl;
}
int main() {
test01();
system("pause");
return 0;
}
5.5关系运算符重载
#include<iostream>
using namespace std;
class person
{
public:
person(string name, int age)
{
m_name = name;
m_age = age;
}
bool operator==(person& p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return true;
}
return false;
}
bool operator!=(person& p)
{
if (this->m_name == p.m_name && this->m_age == p.m_age)
{
return false;
}
return true;
}
string m_name;
int m_age;
};
void test01()
{
person p1("tom", 18);
person p2("jack", 22);
if (p1 == p2)
{
cout << "p1 和p2 是相等的" << endl;
}
else
{
cout <<"布线等" << endl;
}
if (p1 != p2)
{
cout << "p1 和p2 是相等的" << endl;
}
else
{
cout << "布线等" << endl;
}
}
int main() {
test01();
system("pause");
return 0;
}
5.6函数调用运算符重载
函数调用运算符()也可以重载 由于重载后使用的方式非常像函数的调用,因此称为仿函数 仿函数没有固定写法,非常灵活
#include<iostream>
using namespace std;
class myprint
{
public:
void operator()(string test)
{
cout << test<< endl;
}
};
void myprint02(string test) {
cout <<test <<endl;
}
void test01()
{
myprint myprint;
myprint("hello world");
myprint02("hello world");
}
class Myadd
{
public:
int operator()(int num1, int num2)
{
return num1, num2;
}
};
void test02()
{
Myadd myadd;
int ret = myadd(100, 100);
cout <<"ret = " << ret<< endl;
cout << Myadd()(100, 100) << endl;
}
int main() {
test02();
system("pause");
return 0;
}
|