C++类和对象(二)

简介

通过执行 void xxxxFun()对C++中内容进行学习,本次学习包含this、static、const、friend(友元)、类和结构体的区别。主要看注释。

源码

#include <iostream>

using namespace std;

/*this使用
this 是 C++ 中的一个关键字,也是一个 const 指针,
它指向当前对象,通过它可以访问当前对象的所有成员。
this 只能用在类的内部,通过 this 可以访问类的所有成员,包括 private、protected、public 属性的。
注:
	this 是一个指针,要用->来访问成员变量或成员函数

以下this->age指向内部成员age,而age=age是形参age
*/
class Student {
public:
	void SetName(char *name);
	void SetAge(int age);
	void SetScore(float score);
	void show();
	void printThis();
private:
	char *name;
	int age;
	float score;
};
void Student::SetName(char *name)
{
	//name = name;
	this->name = name;
}
void Student::SetAge(int age)
{
	//
	age = age;
	//this->age = age;
}
void Student::SetScore(float score)
{
	this->score = score;
}
void Student::show()
{
	cout << this->name << "的年龄是" << this->age << ",成绩是" << this->score << endl;
}
void ThisFun1(void)
{
	Student *pStu = new Student;
	pStu->SetName("小明");
	pStu->SetAge(15);
	pStu->SetScore(92.5);
	pStu->show();
}
/*this使用
this指向当前对象,对于不同对象this值也不一样

注:
	this 是 const 指针,它的值是不能被修改的,一切企图修改该指针的操作,如赋值、递增、递减等都是不允许的。
	this 只能在成员函数内部使用,用在其他地方没有意义,也是非法的。
	只有当对象被创建后 this 才有意义,因此不能在 static 成员函数中使用

this 实际上是成员函数的一个形参,在调用成员函数时将对象的地址作为实参传递给 this。
不过 this 这个形参是隐式的,它并不出现在代码中,而是在编译阶段由编译器默默地将它添加到参数列表中。
*/
void Student::printThis()
{
	cout << this << endl;
}
void ThisFun2(void)
{
	Student *pStu1 = new Student;
	pStu1->printThis();
	cout << pStu1 << endl;

	Student *pStu2 = new Student;
	pStu2->printThis();
	cout << pStu2 << endl;
}

/*静态成员变量
静态成员变量是一种特殊的成员变量,它被关键字static修饰
注:
	1、static 成员变量的内存既不是在声明类时分配,也不是在创建对象时分配,
	而是在(类外)初始化时分配。反过来说,没有在类外初始化的 static 成员变量不能使用。
	2、static 成员变量不占用对象的内存,而是在所有对象之外开辟内存,即使不创建对象也可以访问。(C中内存4区,static在全局变量区)
*/
class Student2
{
public:
	Student2(char *name, int age, float score);
	void show();
public:
	static int m_total;
private:
	char *m_name;
	int m_age;
	float m_score;
};
//static 成员变量必须在类声明的外部初始化
//具体形式为type class::name = value;
int Student2::m_total = 0;
Student2::Student2(char *name, int age, float score) :
	m_name(name), m_age(age), m_score(score)
{
	m_total++;
}
void Student2::show()
{
	cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << "(当前共有" << m_total << "名学生)" << endl;
}
/*
说明:
1、一个类中可以有一个或多个静态成员变量,所有的对象都共享这些静态成员变量,都可以引用它。
2、static 成员变量和普通 static 变量一样,都在内存分区中的全局数据区分配内存,到程序结束时才释放。
这就意味着,static 成员变量不随对象的创建而分配内存,也不随对象的销毁而释放内存。而普通成员变量在对象创建时分配内存,在对象销毁时释放内存。
3、静态成员变量必须初始化,而且只能在类体外进行。
(初始化时可以赋初值,也可以不赋值。如果不赋值,那么会被默认初始化为 0。
全局数据区的变量都有默认的初始值 0,而动态数据区(堆区、栈区)变量的默认值是不确定的,一般认为是垃圾值。)
4、静态成员变量既可以通过对象名访问,也可以通过类名访问,
但要遵循 private、protected 和 public 关键字的访问权限限制。当通过对象名访问时,对于不同的对象,访问的是同一份内存。
*/
void staticFun(void)
{
	/*static成员变量既可以通过对象访问,也可以通过类来访问*/
	Student2::m_total = 10;//通过类访问
	Student2 stu("小明", 15, 92.5f);
	stu.m_total = 20;//通过对象来访问
	Student2 *pstu = new Student2("小红", 14, 97);
	pstu->m_total = 0;

	//以下创建匿名对象(没有指针指向匿名内存,会造成内存泄漏,只作为示例)
	(new Student2("小明", 15, 90))->show();
	(new Student2("李磊", 16, 80))->show();
	(new Student2("张华", 16, 99))->show();
	(new Student2("王康", 14, 60))->show();
}
/*static成员函数
普通成员函数可以访问所有成员(包括成员变量和成员函数),静态成员函数只能访问静态成员。
静态成员函数与普通成员函数的根本区别在于:
	普通成员函数有 this 指针,可以访问类中的任意成员;而静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数)
*/
class Student3
{
public:
	Student3(char *name, int age, float score);
	void show();
public:
	static int getTotal();
	static float getPoints();
private:
	/*总人数 m_total 和总成绩 m_points 由各个对象累加得到,必须声明为 static 才能共享;
	getTotal()、getPoints() 分别用来获取总人数和总成绩,为了访问 static 成员变量,我们将这两个函数也声明为 static。
	
	C++中静态成员函数的主要目的是访问静态成员。getTotal()、getPoints() 当然也可以声明为普通成员函数,
	但是它们都只对静态成员进行操作,加上 static 语义更加明确。

	和静态成员变量类似,静态成员函数在声明时要加 static,在定义时不能加 static。
	*/
	static int m_total;//总人数
	static float m_points;//总成绩
private:
	char *m_name;
	int m_age;
	float m_score;
};
int Student3::m_total = 0;
float Student3::m_points = 0.0;
Student3::Student3(char *name, int age, float score) :
m_name(name), m_age(age), m_score(score)
{
	m_total++;
	m_points += score;
}
void Student3::show()
{
	cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << endl;
}
//定义静态成员函数
int Student3::getTotal() {
	return m_total;
}
float Student3::getPoints() {
	return m_points;
}
void staticFun2(void)
{
	Student3 *pStu = new Student3("小明", 15, 90.6);
	pStu->show();
	(new Student3("李磊", 16, 80.5))->show();
	(new Student3("张华", 16, 99.0))->show();
	(new Student3("王康", 14, 60.8))->show();
	int total = pStu->getTotal();
	float points = Student3::getPoints();
	cout << "当前共有" << total << "名学生,总成绩是" << points << ",平均分是" << points / total << endl;
}

/*const成员函数与const成员变量

const 成员变量的用法和普通 const 变量的用法相似,只需要在声明时加上 const 关键字。
初始化 const 成员变量只有一种方法,就是通过构造函数的初始化列表.
const 成员函数可以使用类中的所有成员变量,但是不能修改它们的值,这种措施主要还是为了保护数据而设置的。
const 成员函数也称为常成员函数。常成员函数需要在声明和定义的时候在函数头部的结尾加上 const 关键字。
注:
	必须在成员函数的声明和定义处同时加上 const 关键字
函数开头的 const 用来修饰函数的返回值,表示返回值是 const 类型,也就是不能被修改,例如const char * getname()。
函数头部的结尾加上 const 表示常成员函数,这种函数只能读取成员变量的值,而不能修改成员变量的值,例如char * getname() const。

const 也可以用来修饰对象,称为常对象。
一旦将对象定义为常对象之后,就只能调用类的 const 成员(包括 const 成员变量和 const 成员函数)了。const  class  object(params);
*/
class constStudent
{
public:
	constStudent(char *name, int age, float score);
	void show();
	//声明常成员函数
	char *getname() const;
	int getage() const;
	float getscore() const;
private:
	char *m_name;
	int m_age;
	float m_score;
};
constStudent::constStudent(char *name, int age, float score) : m_name(name), m_age(age), m_score(score) { }
void constStudent::show() 
{
	cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << endl;
}
//定义常成员函数
char * constStudent::getname() const 
{
	return m_name;
}
int constStudent::getage() const 
{
	return m_age;
}
float constStudent::getscore() const 
{
	return m_score;
}
void constFun(void)
{
	const constStudent stu("小明", 15, 90.6);
	cout << stu.getname() << "的年龄是" << stu.getage() << ",成绩是" << stu.getscore() << endl;//只能访问const成员变量和函数
}
/*友元函数和友元类
在 C++ 中,一个类中可以有 public、protected、private 三种属性的成员,通过对象可以访问 public 成员,
只有本类中的函数可以访问本类的 private 成员。现在,我们来介绍一种例外情况——友元(friend)。
借助友元(friend),可以使得其他类中的成员函数以及全局范围内的函数访问当前类的 private 成员。

注:
	友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。
一个函数可以被多个类声明为友元函数,这样就可以访问多个类中的 private 成员。

说明:
	1、友元的关系是单向的而不是双向的。如果声明了类 B 是类 A 的友元类,
	不等于类 A 是类 B 的友元类,类 A 中的成员函数不能访问类 B 中的 private 成员。
	2、友元的关系不能传递。如果类 B 是类 A 的友元类,类 C 是类 B 的友元类,不等于类 C 是类 A 的友元类。
*/
class Address;//提前声明
class friendStudent
{
public:
	friendStudent(char *name, int age, float score);
public:
	void show(Address *addr);
private:
	char *m_name;
	int m_age;
	float m_score;
};
class Address
{
private:
	char *m_province;//省份
	char *m_city;//城市
	char *m_district;//区(市区)
public:
	Address(char *province, char *city, char *district);
	friend void friendStudent::show(Address *addr);//将Student类中的成员函数show()声明为友元函数

	/*不仅可以将一个函数声明为一个类的“朋友”,还可以将整个类声明为另一个类的“朋友”,这就是友元类。
	友元类中的所有成员函数都是另外一个类的友元函数。
	例如将类 B 声明为类 A 的友元类,那么类 B 中的所有成员函数都是类 A 的友元函数,
	可以访问类 A 的所有成员,包括 public、protected、private 属性的。
	
	注:
		除非有必要,一般不建议把整个类声明为友元类,而只将某些成员函数声明为友元函数,这样更安全一些。
	*/
	//friend class friendStudent;// 将Student类声明为Address类的友元类
};
friendStudent::friendStudent(char *name, int age, float score) :
	m_name(name), m_age(age), m_score(score){}
void friendStudent::show(Address *addr)
{
	cout << m_name << "的年龄是 " << m_age << ",成绩是 " << m_score << endl;
	//友元函数不同于类的成员函数,在友元函数中不能直接访问类的成员,必须要借助对象。
	//cout << m_province << m_city << m_district << endl;直接访问是错误的
	cout << "家庭住址:" << addr->m_province << "省" << addr->m_city << "市" << addr->m_district << "区" << endl;
}
Address::Address(char *province, char *city, char *district) :
	m_province(province), m_city(city), m_district(district){}
void friendFun(void)
{
	friendStudent stu("小明", 16, 95.5f);
	Address addr("陕西", "西安", "雁塔");
	stu.show(&addr);

	friendStudent *pstu = new friendStudent("李磊", 16, 80.5);
	Address *paddr = new Address("河北", "衡水", "桃城");
	pstu->show(paddr);
}
/*类的作用域

类其实也是一种作用域,每个类都会定义它自己的作用域。
在类的作用域之外,普通的成员只能通过对象(可以是对象本身,也可以是对象指针或对象引用)来访问,
静态成员既可以通过对象访问,又可以通过类访问,而 typedef 定义的类型只能通过类来访问。

*/
class A
{
public:
	typedef int INT;
	static void show();
	void work();
};
void A::show() { cout << "show()" << endl; }
void A::work() { cout << "work()" << endl; }
void typedefFun(void)
{
	A a;
	a.work();//通过对象访问普通成员
	a.show();//通过对象访问静态成员
	A::show();//通过类访问静态成员
	A::INT n = 10;//通过类访问 typedef 定义的类型
}
/*一个类就是一个作用域能够很好的解释为什么我们在类的外部定义成员函数时必须同时提供类名和函数名。
在类的外部,类内部成员的名字是不可见的。
一旦遇到类名,定义的剩余部分就在类的作用域之内了,这里的剩余部分包括参数列表和函数体。
结果就是,我们可以直接使用类的其他成员而无需再次授权了。*/
class A2 {
public:
	typedef char* PCHAR;
public:
	void show(PCHAR str);
private:
	int n;
};
/*
A::PCHAR A::show(PCHAR str) {
	cout << str << endl;
	n = 10;
	return str;
}*/
void A2::show(PCHAR str) {
	cout << str << endl;
	n = 10;
}
void typedefFun2(void)
{
	A2 obj;
	obj.show("123");


}
/*C++中类(class)和C中结构体(struct)的区别
C++中的 struct 和 class 基本是通用的,唯有几个细节不同:
	使用 class 时,类中的成员默认都是 private 属性的;而使用 struct 时,结构体中的成员默认都是 public 属性的。
	class 继承默认是 private 继承,而 struct 继承默认是 public 继承。
	class 可以使用模板,而 struct 不能。

在编写C++代码时,建议使用 class 来定义类,而使用 struct 来定义结构体,这样做语义更加明确。
以下是一个反面教材
代码可以通过编译,说明 struct 默认的成员都是 public 属性的,
否则不能通过对象访问成员函数。如果将 struct 关键字替换为 class,那么就会编译报错。
*/
struct StructStudent
{
	StructStudent(char *name, int age, float score);
	void show();
	char *m_name;
	int m_age;
	float m_score;
};
StructStudent::StructStudent(char *name, int age, float score) : m_name(name), m_age(age), m_score(score) { }
void StructStudent::show() {
	cout << m_name << "的年龄是" << m_age << ",成绩是" << m_score << endl;
}
void StructFun(void)
{
	StructStudent stu("小明", 15, 92.5f);
	stu.show();
	StructStudent *pstu = new StructStudent("李华", 16, 96);
	pstu->show();
}


int main()
{
	
	StructFun();

	system("pause");

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值