一.类对象作为类成员
类可以作为另一个类的成员
代码:
#include <iostream>
using namespace std;
class phone {
public:
string shouji;
phone(string shouji1) :shouji(shouji1) {
cout << "phone的构造函数调用" << endl;
}
~phone() {
cout << "phone的析构函数调用" << endl;
}
};
class person {
public:
int age;
string name;
phone shouji;
//隐式转换相当于shouji=phone(shouji1)
person(int a, string name1, string shouji1) :age(a), name(name1), shouji(shouji1) {
cout << "person的构造函数调用" << endl;
}
~person() {
cout << "person的析构函数调用" << endl;
}
};
void fun() {
person p(23, "小明", "苹果");
}
int main() {
fun();
return 0;
}
注意:
创建类时,被包含的类的构造函数先调用,随后外层类的构造函数再调用,析构1的时候正好相反,外部类先析构,内部类再析构。
二.静态成员
静态成员就是在成员变量前面加上static关键字,称为静态成员。
静态成员分为静态成员变量和静态成员函数。
2.1静态成员变量
。所有对象共享同一份数据
。在编译阶段分配内存。
。类内声明,类外初始化·静态成员函数
静态成员必须在类外初始化,否则编译器认为只声明,但是没有实际定义,链接发生错误。
代码:
#include <iostream>
using namespace std;
class person {
public:
static int age;
};
int person::age = 10;
void fun() {
person p;
p.age = 90;
person p1;
cout << p1.age << endl;
}
int main() {
fun();
return 0;
}
静态成员变量,不仅可以通过对象访问,也可以通过类名访问。静态成员变量也是有访问权限的。
代码:
#include <iostream>
using namespace std;
class person {
public:
static int age;
};
int person::age = 10;
void fun() {
person p;
p.age = 90;
cout << person::age << endl;
}
int main() {
fun();
return 0;
}
2.2静态成员函数
。所有对象共享同一个函数
。静态成员函数只能访问静态成员变量
代码:
#include <iostream>
using namespace std;
class person {
public:
static int age;
static void fun(int a) {
age = a; //只能调用静态成员变量
cout << "静态函数fun调用" << endl;
}
};
int person::age = 100;
void dioayong() {
person p;
p.fun(99); //对象调用
person::fun(66); //类名调用
cout << p.age << endl;
}
int main() {
dioayong();
return 0;
}
同样,静态成员函数也是可以通过类名来调用,需要注意静态成员函数只能调用静态成员变量。
三.this指针
3.1成员变量和函数的存储
在C++中,类内的的成员变量和成员函数分开存储
只有非静态成员变量才属于类的对象上
在C++中, 空类也占用一个字节。C++编译器会给每个空对象也分配一个字节空间,是为了区分对象占内存的位置。
代码:
#include <iostream>
using namespace std;
class person {
};
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
在类中同样具有内存对齐的特性
代码:
#include <iostream>
using namespace std;
class person {
public:
int a;
char b;
};
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
此外,成员函数和静态成员变量都不存储在类上,也就是只有非静态成员变量存储在类中
代码:
#include <iostream>
using namespace std;
class person {
public:
int a;
static int b;
void fun() {
cout << "fun函数调用" << endl;
}
static void fun1() {
cout << "fun1函数调用" << endl;
}
};
int person::b = 10;
void fun() {
person p;
cout<<sizeof(p);
}
int main() {
fun();
return 0;
}
3.2this指针使用
每一个非静态成员函数只会诞生一份函数实例,也就是说多个同类型的对象会共用一块代码那么问题是:这一块代码是如何区分那个对象调用自己的呢?
C++通过提供特殊的对象指针,this指针,解决上述问题。this指针指向被调用的成员函数所属的对象
注意:
1.this指针是隐含每一个非静态成员函教内的一种指针
2.this指针不需要定义,直接使用即可
this指针的用途:
·当形参和成员变量同名时,可用this指针来区分同名形参和变量
·在类的非静态成员函数中返回对象本身,可使用return *this
代码:
#include <iostream>
using namespace std;
class people {
public:
int age;
people(int age) {
this->age = age;
}
};
void zhixing() {
people p(10);
cout << p.age << endl;
}
int main() {
zhixing();
return 0;
}
返回自身时,注意要返回引用类型,返回普通值类型时,返回值是本身的副本
#include <iostream>
using namespace std;
class people {
public:
int age;
people(int age) {
this->age = age;
}
people& add(const people& p) {
this->age += p.age;
return *this;
}
};
void zhixing() {
people p1(10);
people p2(20);
p2.add(p1).add(p1).add(p1).add(p1);
cout << p2.age << endl;
}
int main() {
zhixing();
return 0;
}
四.空指针访问成员函数
C++中空指针也是可以调用成员函数的,但是也要注意有没有用到this指针
代码:
#include <iostream>
using namespace std;
class person {
public:
int age;
void fun1() {
cout << "fun1调用" << endl;
}
void fun2() {
cout << "fun2调用" << age << endl;
}
};
void diaoyong() {
person* p = NULL;
p->fun1();
p->age = 10;
p->fun2();
}
int main() {
diaoyong();
return 0;
}
只能成功调用没有this指针的函数,因为此时this是空指针,含有this的调用
代码:
#include <iostream>
using namespace std;
class person {
public:
int age;
void fun1() {
cout << "fun1调用" << endl;
}
void fun2() {
if (this == NULL) {
return;
}
cout << "fun2调用" << age << endl;
}
};
void diaoyong() {
person* p = NULL;
p->fun1();
p->fun2();
}
int main() {
diaoyong();
return 0;
}
增加代码的健壮性,判断this指针是空指针的时候,跳出函数。
五.const修饰成员函数
常函数:
1.成员函数后加const后我们称为这个函数为常函数。
2.常函数内不可以修改成员属性。
3.成员属性声明时加关键字mutable后,在常函数中依然可以修改。
常对象:
1.声明对象前加const称对象为常对象。
2.常对象只能调用常函数和用mutable修饰的成员变量。
5.1常函数
this指针本质是指针常量,指针的指向是不可以修改的(person* const this),但是this指针指向地址的值是可以发生改变的。
常函数const要加在函数参数列表后面
代码:
#include <iostream>
using namespace std;
class person {
public:
int age;
void showage(int m) const{
// age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
};
void fun() {
person p;
p.age = 10;
p.showage(7);
}
int main() {
fun();
return 0;
}
此时编译器会报错,此时age在函数内是不可改变的。但是函数传的参数,仍然是可以改变的。
#include <iostream>
using namespace std;
class person {
public:
mutable int age;
void showage(int m) const{ //常函数
age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
};
void fun() {
person p;
p.age = 10;
p.showage(7);
}
int main() {
fun();
return 0;
}
成员属性声明时加关键字mutable后,在常函数中依然可以修改。
5.2 常对象
代码:
#include <iostream>
using namespace std;
class person {
public:
mutable int age;
void showage1(int m) const{
//age = 89; //报错
m = 100;
cout << "age=" << age <<" m=" << m << endl;
}
void showage2(int m) {
age = 89;
m = 100;
cout << "age=" << age << " m=" << m << endl;
}
};
void fun() {
const person p;
p.age = 10;
p.showage1(7);
//p.showage2(7); 报错
}
int main() {
fun();
return 0;
}
常对象只能调用常函数和用mutable修饰的成员变量。普通函数和普通成员变量不能调用
六.友元
友元关键字:friend
友元的三种实现:
1.全局函数做友元
2.类做友元
3.成员函数做友元
6.1全局函数做友元
代码:
#include <iostream>
using namespace std;
class home {
friend void func(home& p);
public:
home(string keting, string woshi, string cuosuo):keting(keting),woshi(woshi),cuosuo(cuosuo) {
}
string keting;
private:
string woshi;
protected:
string cuosuo;
};
void func(home &p) {
cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
}
void fun() {
home p("客厅", "卧室", "厕所");
func(p);
}
int main() {
fun();
//cout << p.keting << ' ' << p.woshi << ' ' << p.cuosuo << endl;
//保护和私有属性的不能访问
return 0;
}
有元函数不是类的成员函数,但是却又权限调用类的所有成员变量
6.2类做友元
#include <iostream>
using namespace std;
class building {
friend class goodgay; //声明友元类
public:
building();
string keting;
private:
string cesuo;
protected:
string woshi;
};
building::building() {
keting = "客厅";
cesuo = "厕所";
woshi = "卧室";
}
class goodgay {
public:
goodgay();
void show();
private:
building* p;
};
void goodgay::show() {
cout << this->p->keting << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
}
goodgay::goodgay() {
p = new building;
}
void f() {
goodgay a;
a.show();
}
int main() {
f();
return 0;
}
类做友元,类中的所有成员函数都能访问友元类中所有成员。
6.3成员函数做友元
代码:
#include <iostream>
using namespace std;
class building;
class goodgay {
public:
goodgay();
void show1(building& p);
private:
building* p;
};
class building {
friend void goodgay::show1(building& p); //声明友元类
public:
building();
string keting;
private:
string cesuo;
protected:
string woshi;
};
building::building() {
keting = "客厅";
cesuo = "厕所";
woshi = "卧室";
}
void goodgay::show1(building& p1) {
cout <<p1.keting << ' ' << p1.cesuo << ' ' << p1.woshi << endl;
}
//void goodgay::show2() {
// cout << this->p->ketipng << ' ' << this->p->cesuo << ' ' << this->p->woshi << endl;
//}
//无权限
goodgay::goodgay() {
p = new building;
}
void f() {
goodgay a;
building b;
a.show1(b);
}
int main() {
f();
return 0;
}
注意类要先声明一下,防止报错,与全局函数做友元不同的是,要加上作用域。