C++特殊成员

目录

一、const成员

        1.const数据成员

        2.const成员函数

        3.const对象

二、static成员

        1.static数据成员

  2.static成员函数

3.static对象

三、友元

        1.友元的定义

        2.友元函数

        3.友元类

        4.互为友元类(增加)

四、this指针与explicit

        1.explicit作用

        2.this指针


一、const成员

        1.const数据成员

                (1).const类型变量是不可修改的(只读模式).

                (2).必须采用初始化参数列表的方式进行初始化.

class Person
{
public:
	Person(string name,int age) :age(age)
	{
		Person::name = name; //可以这样赋值,也可以用初始化参数列表方法
		//Person::age = age; --->报错,const修饰的参数只能用初始化参数列表方式进行初始化
	}
protected:
	string name;
	const int age;
};

        2.const成员函数

                (1).写法上,const要加在函数后面

                (2).常成员函数不能修改数据成员(只读数据成员)

void print()const//常成员函数
	{
		//name = "修改"; --->报错,常成员函数中不能修改数据
		//age = 19; -->常成员数据也不能修改
		cout << "常成员函数" << endl;
	}

                (3).常成员函数可以与普通函数同时存在

void print()//普通函数
	{
		//age = 1001; --->错误 只读模式 不能修改
		cout << name << " " << age << endl;
	}
	void print()const//常成员函数
	{
		//name = "修改"; --->报错,常成员函数中不能修改数据
		//age = 19; -->常成员数据也不能修改
		cout << "常成员函数" << endl;
	}

注: ● 普通函数和常成员函数相同时,普通对象优先调用普通函数

        ● 普通对象可以调用常成员函数

        3.const对象

                (1).定义:const修饰的对象

                (2).常对象只能调用常成员函数

#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
	Person(string name,int age) :age(age)
	{
		Person::name = name; //可以这样赋值,也可以用初始化参数列表方法
		//Person::age = age; --->报错,const修饰的参数只能用初始化参数列表方式进行初始化
	}
	void print()//普通函数
	{
		//age = 1001; --->错误 只读模式 不能修改
		cout << name << " " << age << endl;
	}
	void print()const//常成员函数
	{
		//name = "修改"; --->报错,常成员函数中不能修改数据
		//age = 19; -->常成员数据也不能修改
		cout << "常成员函数" << endl;
	}
	void printData()
	{
		cout << "普通函数" << endl;
	}
protected:
	string name;
	const int age;
};
int main()
{
	Person MM("Miss Du", 19);
	MM.print();//普通对象优先调用普通函数
	//两者都有时只能调用普通函数,无法强行调用常成员函数
	//若只有常成员函数也可以调用常成员函数
	const Person GG("Mr Y", 19);
	GG.print();//输出常成员函数  常对象调用常成员函数
	//GG.printData();---->常对象只能调用常成员函数
	while (1);
	return 0;
}

二、static成员

     注:● static成员不属于对象,是属于类的,这意味着static成员是属于所有对象的(共有的),调用时可以不用对象(也可以通过对象访问).

            ● static成员依旧受权限限定.

        1.static数据成员

                (1).必须在类外初始化,初始化时不再需要static修饰,但是需要类名限定.

                (2).类中初始化是错误的,不能采用初始化参数列表方式初始化.

class Person
{
public:
	
	//Person(int age):age(age){}  
//-->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
protected:
	string name;
	static int age;
};
//类外初始化,不再需要static修饰,但是需要类名限定
int Person::age = 1;

  2.static成员函数

                (1).样式:static写在函数前面即可

                (2).调用非静态成员时必须要指定对象.

class Person
{
public:
	
	//Person(int age):age(age){}  
	//---->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
	Person(string name) :name(name)
	{
		age++;
	}
	static void printMM();//类外实现--->静态函数
	static void printData(Person& MM)//类内声明,类内实现,可以通过对象的引用访问name数据成员
	{
		cout << MM.name << '\t' << age << endl;
	}
protected:
	string name;
public:
	static int age;
};
//类外初始化,不再需要static修饰
void Person::printMM()
{
	//调用非静态数据成员,必须要指定对象
	//cout << name << endl; --->当这个函数不采用对象去调用,name没有来源,报错
	Person MM("Miss DU");
	cout << MM.name << endl;
	//静态数据成员可直接调用,也可以通过对象调用
	cout << age << endl;
	cout << MM.age << endl;
	cout << "静态成员函数" << endl;
}

3.static对象

         注:释放是最后释放的

#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
	//Person(int age):age(age){}  
	//---->age不是类的非静态数据成员或者基类,因此在类内初始化或者用初始化参数列表初始化都不可以
	Person(string name="") :name(name)
	{
		age++;
	}
	static void printMM();//类外实现
	static void printData(Person& MM)//类内声明,类内实现,可以通过对象的引用访问name数据成员
	{
		cout << MM.name << '\t' << age << endl;
	}
protected:
	string name;
public:
	static int age;
};
//类外初始化,不再需要static修饰,但是需要类名限定
int Person::age = 18;
//类外初始化,不再需要static修饰
void Person::printMM()
{
	//调用非静态数据成员,必须要指定对象
	//cout << name << endl; --->当这个函数不采用对象去调用,name没有来源,报错
	Person MM("Miss DU");
	cout << MM.name << endl;
	//静态数据成员可直接调用,也可以通过对象调用
	cout << age << endl;
	cout << MM.age << endl;
	cout << "静态成员函数" << endl;
}
int main()
{
	
	//静态数据成员访问可以不用对象调用
	cout << Person::age << endl;
	//静态数据成员可以通过对象去访问
	Person MM("Miss Du");
	cout << MM.age << endl;				//age=20
	//静态数据成员是共有的
	Person GG[3];						//age=23;
	Person* pMM = new Person("newMM");	//age=24
	cout << Person::age << endl;		//age=24
	cout << pMM->age << endl;			//age=24
	cout << MM.age << endl;				//age=24
	delete pMM;
	pMM = nullptr;

	cout << endl;
	//静态成员函数
	Person::printMM();
	MM.printMM();				//---->三者等价
	Person::printData(MM);
	while (1);
	return 0;
}

三、友元

        1.友元的定义

                ● friend描述的关系.友元只是提供一个场所,赋予对象具有打破类的权限定(无视权限).

                ● 可以理解为朋友的是自己的,自己的也是自己的.(自我理解,或许有误)              

        2.友元函数

                (1).普通友元函数

#include<iostream>
#include<string>
using namespace std;
void printData();//声明
class Person
{
public:
	Person(string name, int age) :name(name), age(age){}
	void print()
	{
		cout << name << '\t' << age << endl;
	}
	friend void printData()
	{
		//不属于类,不能直接访问成员  ---> 对非静态成员"Person::name"的非法引用
		//cout << name << '\t' << age << < endl;
		//友元函数提供一个场所,让对象无视权限
		Person GG("Mr Y", 19);
		cout << GG.name << '\t' << GG.age << endl;
	}
protected:
	string name;
private:
	int age;
	friend void printData2(Person& MM);//类内声明
};
//类外实现友元函数--->//不需friend修饰,不需要类名限定
void printData2(Person& MM)
{
	cout << MM.name << '\t' << MM.age << endl;
}
//void printData()
//{
//	//不属于类,不能直接访问成员  ---> 对非静态成员"Person::name"的非法引用
//	//cout << name << '\t' << age << < endl;
//	//友元函数提供一个场所,让对象无视权限
//	Person GG("Mr Y", 19);
//	cout << GG.name << '\t' << GG.age << endl;
//}
int main()
{
	Person MM("Miss Du", 19);
	MM.print();
	printData();	//直接调用友元函数
	printData2(MM);
	while (1);
	return 0;
}

                (2).若以另一个类的成员函数充当友元函数,顺序如下:

                        ● B类--->A类--->A类的友元函数(B类的成员函数)

class B
{
public:
	void printA();
	void printData();
protected:
};
class A
{
public:
	friend void B::printA();
protected:
	string name = "A";
};
//成员函数实现,一定是在另一个类的下面实现
void B::printA()
{

	A a;
	cout << a.name << endl;
}
void B::printData()
{
	A a;
	错误 ,不是他的A类的友元函数,所以不能访问保护和私有属性
	//cout << a.name << endl;
}

        3.友元类

                注:一个类是另一个类的友元类                

#include <iostream>
#include<string>
using namespace std;
class Person
{
	friend class MM;
public:
	Person(string name, int age) :name(name), age(age){}
protected:
	string name;
	int age;

};
class MM
{
public:
	void print()
	{
		Person mm("Miss Du", 19);
		cout << mm.name << "\t" << mm.age << endl;
	}
	void printMM(Person& mm)
	{
		cout << mm.name << "\t" << mm.age << endl;
	}
	Person& printmm(Person& mm)
	{
		return mm;
	}
protected:

};
int main()
{
	Person mm("Miss Du", 19);
	MM mm2;
	mm2.print();
	//mm2.printMM(mm);
	//cout<<(mm2.printmm(mm)).name<<endl; --->错误,出了友元类,没有权限
	while (1);
	return 0;
}

        4.互为友元类(增加)

#include <iostream>
#include<string>
using namespace std;
//互为友元类
class Person
{
	friend class MM;
public:
	Person() = default;
	Person(string name, int age) :name(name), age(age){}
	//void printData()//无法在此处写打印MM的数据,因为会显示MM没有定义
	//{
	//	MM mm("Miss Du", 19);
	//	cout << mm.name << "\t" << mm.age << endl;
	//}
	void printData();//可以通过类内定义,类外实现
protected:
	string name;
	int age;
};
class MM
{
	friend class Person;
public:
	MM(string name, int age) :name(name), age(age){}
	void printData()
	{
		Person gg("Mr Y", 19);
		cout << gg.name << "\t" << gg.age << endl;
	}
protected:
	string name;
	int age;
};
void Person::printData()
{
	MM mm("Miss Du", 19);
	cout << mm.name << "\t" << mm.age << endl;
}
int main()
{
	Person mm1;
	mm1.printData();
	MM mm2("Miss Du", 19);
	mm2.printData();
	while (1);
	return 0;
}

四、this指针与explicit

        1.explicit作用

                ● 修饰构造函数使用,不让隐式转换构造

#include<iostream>
#include<string>
using namespace std;
class Person
{
public:
	explicit Person(int age) :age(age){}
	explicit Person(string name, int age) :name(name), age(age){}
	void print()
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
class MM
{
public:
	MM(string name) :name(name){}
	MM(string name, int age) :name(name), age(age){}
	void print()
	{
		cout << name << "\t" << age << endl;
	}
protected:
	string name;
	int age;
};
int main()
{
	//explicit 不让隐式转换构造
	//Person mm3 = 12;--->不存在从“int”转换为“Person”的适当构造函数
	Person mm1(19);		//可以如此初始化
	MM mm = "Miss Du";	//可以如此初始化
	while (1);
	return 0;
}

        2.this指针

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

                ● 充当函数返回值,返回对象自身,用*this表示对象本身

                ● 静态成员函数中是不能使用this指针

#include<iostream>
#include<string>
using namespace std;
class MM
{
public:
	MM(string name) :name(name){}
	MM(string name, int age) :name(name), age(age){}
	void initData(string name, int age)
	{
		//普通函数不存在初始化参数列表方法--->使用this指针
		this->name = name;
		//类名限定 帮助计算机去识别
		MM::age = age;

	}
	void print()
	{
		cout << this->name << "\t" <<this->age << endl;
	}
	void printThis()
	{
		cout << this << endl;
	}
	MM returnMM()
	{
		return *this;
	}
	static void printMM3()
	{
		//cout << this->name << endl;--->this只能用于非静态成员函数内部
		MM mm("Miss Du", 20);
		cout << mm.name << "\t" << mm.age << endl;
	}

protected:
	string name;
	int age;
};
int main()
{
	MM mm("Miss Du",19);
	mm.print();
	mm.initData("Mr Y", 20);
	mm.print();
	cout << &mm << endl;
	mm.printThis();//this为对象的地址
	MM mm2("dmw", 19);
	cout << &mm2 << endl;
	mm2.printThis();
	
	MM::printMM3();
	while (1);
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值