Day5 :特殊成员const static 以及友元 this explicit的应用

const:

①数据成员:必须用初始化成员列表初始化。

	wbm(string name,const int age):name(name),age(age){}

②常成员函数:1.const在最后面

                           2.不可以借此作为接口来修改数据成员,也就是只读模式

                           3.可以和普通函数同时且同名存在,遵循“名当户对”的原则,普->普,若是在没有普通函数,则 调用常函数。

class wbm
{
public:
	wbm(string name,const int age):name(name),age(age){}
	void print()const
	{
		cout << "i'm an ordinary hanshu" << endl;
	}
	void print()
	{
		cout << "i'm a normal hanshu" << endl;
	}

protected:
	const int age;
	string  name;
private:
};
int main()
{
	wbm gzj("王二狗", 12);
	gzj.print();
	const wbm jiejie("wbm", 21);
	jiejie.print();
	return 0;
}

Day5 :特殊成员const static 以及友元 this explicit的应用

 ③常对象:仅能调用常函数

 static成员:

前置声明:

             1.属于类的而非某个对象的,也就是  共有 。 调用可以不用某个对象来调用。

(共有的这个性质,我们将会在下面初始化成员列表中  用某个数据成员++ 来验证)

             2.但仍然会受到权限的限定。(在直接通过 类名限定加上::访问就会体现的很明显)

①static数据成员:

        必须类外初始化,在类外的时候只需要类型+类名限定(即无需static修饰)。那么在类中或者用初始化成员列表中初始化就是不被允许的。

class wbm
{
public:

protected:
	static int age;
	string name;
};
int wbm::age = 100;

 展示一下通过类来调用

Day5 :特殊成员const static 以及友元 this explicit的应用

 共用的具体体现:

class wbm
{
public:
	wbm(const string name=" ") :name(name)
	{
		age++;//这样写表示,每构造一个函数都会让静态age自增一次
	}
	static int age;
protected:
	const string name;
};
int wbm::age = 1;

int main()
{
	cout << wbm::age << endl;//1
	wbm k1("k1");//2
	cout << wbm::age << endl;
	wbm k2("k2");//3
	cout << wbm::age << endl;
	wbm k[3];//6
	cout << wbm::age << endl;
	wbm* k3 = new wbm;//7
	cout << wbm::age << endl;
	return 0;
}

注意若加上了default默认函数,通过默认构造的函数age不会++(第二条路)

故我们通常在初始化列表里加上初始化,方便用。

其次,若想实现age++不能再初始化成员列表里加上int age;否则最终age始终停留在初始化的age值,不会在变(亲测)。

只要对静态数据成员的值更新一次,就可以保证所有对象都会存取更新后的值!!

②成员函数:

        1.static放在函数名前面,类外实现无需static修饰。当然在类中实现也是可以的。        

        2.若调用了非静态数据成员,必须指定对象(解决:传一个对象参数进来)

        解决代码实现:

//类中定义这么写	
static void printdata(const wbm& mm)
	{
		cout <<mm.name<< endl;
	}
//main中使用这么用
wbm k1("k1");
wbm::printdata(k1);

        3.若调用的是静态数据:无要求。

static void printstatic_data()
	{
		cout << age << endl;
	}

③static对象:

最后释放!!! 

友元Friend :

①定义:提供一个场所,赋予对象具有打破类的权限限定(无视权限)

(当然,仍然是通过对方的对象访问数据)

②友元函数:(不属于类,不能直接访问成员,若在类外实现,不需要friend修饰,不需要类名限定)(也不可以用对象来,访问友元函数

1.放在函数名前

2.实现方式一:若传入了参数,是可以在类里面实现的,然后在main里面直接使用。

//类中:
	friend void print_no_static(const pig&mm)
	{
		cout << mm.age << "\t" << mm.name << endl;
	}
main中:
	pig jie ("jie", 18);
	print_no_static(jie);

实际上传入参数,在类外实现也是可以的

(在类中相当于声明一下。)

实现方式二:若不传入参数,且在类中实现,main中是无法直接用的,需要前置声明函数。

前置声明:

Day5 :特殊成员const static 以及友元 this explicit的应用

void print_no_static();
class pig
{
public:
	pig(string name, int age) :name(name), age(age){}
	friend void print_no_static()
	{
		cout << height << endl;
	}
	friend void print_static();
protected:
	int age;
	string name;
private:
	static int height;
};
int pig::height = 100;
//void print_no_static(const pig &mm)
//{
//	cout << mm.age << "\t" << mm.name << endl;
//}
void print_static()
{
	cout << pig::height << endl;
}
int main()
{

	pig jie ("jie", 18);
	print_no_static();
	return 0;
}

③以另一个类的成员函数充当友元函数:

顺序 :

        B类

        A类:friend

        A类友元(即B成员函数)的实现 

目的:该函数需要访问另外一个类的私有或者保护成员,比对其进行一些操作。现实生活中的一个例子就是:老师类需要对学生的成绩进行修改。

#include<iostream>
using namespace std;

class student;
class teacher
{
public:
	void change_student_grade(student &wbm);
};
class student
{
public:
	student(int grade):grade(grade){}
	friend void teacher::change_student_grade(student &wbm);
	void printGrade()
	{
		cout << "成绩"<<grade << endl;
	}
protected:
	int grade;
private:
};
void teacher::change_student_grade(student &wbm)
{
	wbm.grade = 100;
}
int main()
{
	student wbm(99);
	wbm.printGrade();
	teacher gzj;
	gzj.change_student_grade(wbm);
	wbm.printGrade();
	return 0;
}

④友元类:

1.a,b类:在A类中告诉我有friend b类,那么b类中一个函数中创建a类对象A(也可以现在函数中创建对象,也可以传引用),则a对象所有属性均可访问

目的:使用单个声明使Y类的所有函数成为类X的友元,它提供一种类之间合作的一种方式,使类Y的对象可以具有类X和类Y的功能。

#include<iostream>
using namespace std;

class student;
class teacher
{
public:
	void print(student& mm);
};
class student
{
public:
	friend teacher;
	student(string name, int age) :name(name), age(age)
	{

	}
protected:
	string name;
	int age;
};
void teacher::print(student &mm)
{
	cout << "name=" << mm.name << endl;
	cout << "age=" << mm.age << endl;
}
int main()
{
	teacher jie;
	student wbm("wbm", 18);
	jie.print(wbm);
	return 0;
}

注:除了友元类就不再拥有权限了,(下面在main中用cout一个返回引用对象函数证明)

 

class student
{
public:
	friend class teacher;
	student(string name, int age) :name(name), age(age) {}
	
protected:
	string name;
	int age;
};
class teacher
{
public:
	void print(student& mm)
	{
		cout << mm.name << "\t" << mm.age << endl;
	}
	student& returnstudent(student& mm)
	{
		return mm;
	}
};
int main()
{
	student wbm("wbm", 18);
	teacher jie;
	jie.print(wbm);
	//jie.returnstudent(wbm).name << endl;
	//错误,一旦出了友元类,就就不再拥有权限
	return 0;
}

补充:互为友元类的写法

(在单向的基础上,加上类外实现的方法)

class student
{
public:
	friend class teacher;
	student(string name) :name(name){}
	void printT();
protected:
	string name;
	int age;
};
class teacher
{
public:
	friend class student;
	teacher(string name) :name(name) { }
	void printS()
	{
		student wbm("wbm");
		cout << wbm.name << endl;
	}
protected:
	string name;
};
void student::printT()
{
	teacher jie("jie");
	cout << jie.name << endl;
}
int main()
{
	student mm("mm");
	mm.printT();
	
	teacher gg("jie");
	gg.printS();
	return 0;
}

 explicit:

针对于构造函数的隐式类型转换问题(不给他转),也就是不给用B b={ }来初始化。

只允许显式: B  b();

this指针:

this指针”指向了成员函数作用的对象

①避免形参名和数据成员同名,通指对象的地址

②充当函数返回值,返回对象自身,用*this表示对象本身(套娃)

③静态成员函数中是不能使用this指针(类外无this)

以下来通过写一个接口initdata来展示this的用法(不用初始化成员列表的时候,不太好分区分,this可以。)

#include<iostream>
using namespace std;

class student
{
public:
	void initdata(string name, int age)
	{
		//区分法一:类名限定
		student::name = name;
		//区分法二:this
		this->age = age;
	}
	void print()
	{
		cout << this->age << endl;
	}
	student& returnstudent()
	{
		return *this;
	}
protected:
	int age;
	string name;
};

int main()
{
	student wbm;
	wbm.initdata("wbb", 18);
	wbm.returnstudent().returnstudent().returnstudent().print();
	//套大娃。
	return 0;
}

上一篇:Scrum冲刺-day5


下一篇:day5