C/C++教程

C++初阶 —— 类与对象(三)

本文主要是介绍C++初阶 —— 类与对象(三),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

一,初始化列表

二,static成员

三,C++11的成员初始化新玩法

四,友元

五,内部类


一,初始化列表

构造函数体赋值

  • 构造函数体内的语句,只能称为赋初值,而不能称为初始化;
  • 因为初始化只能一次,而构造函数体内可多次赋值;
//类A
class A
{
public:
	A(int a = 1)
	{
		_a = a;
		cout << "A(int a = 1)" << endl;
	}
	A& operator = (const A& a)
	{
		if (this != &a)
			_a = a._a;
		cout << "A& operator = (const A& a)" << endl;
		return *this;
	}
private:
	int _a;
};
//类B
class B
{
public:
	B(int a, int b)
	{
		_b = b;
		_aa = A(a); //A(a)为匿名函数,生命周期只在这一行
	}
private:
	int _b;
	A _aa;
};

int main()
{
	B b(10, 20);
	return 0;
}

初始化列表

  • 冒号开始,逗号分隔数据成员列表,后跟括号中为初始值或表达式;
  • 成员变量(初始值)成员变量(初始值)...
class B
{
public:
	B(int a, int b)
		:_aa(a)
	{
		_b = b;
	}
private:
	int _b;
	A _aa;
};

注:

  • 成员变量在初始化列表中只能出现一次(即只能初始化一次);
  • 类中包括以下成员,必须放在初始化列表位置进行初始化:引用成员变量、const成员变量、自定义类型成员(无默认构造函数,可理解为显式的调用构造函数);
  • 尽量使用初始化列表初始化,因为对于自定义类型成员变量,一定会先使用初始化列表初始化;
  • 成员变量在类中,声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的次序无关;
  • 初始化列表可与函数体内赋值混用;
class B
{
public:
	B(int a, int b1, int& b2)
		:_aa(a)
        ,_b1(b1)
        ,_b2(b2)
	{}
private:
	const int _b1;
    int& _b2;
	A _aa;
};

explicit 关键字

  • 对单个参数的构造函数,具有隐式类型转换;
  • 用explicit修饰的构造函数,将禁止单个参数的构造函数隐式转换;
  • 参考书《深度探索C++对象模型》;
class A
{
public:
	A(int a)
		:_a(a)
	{
		cout << "A(int a = 1)" << endl;
	}
	A(const A& a)
	{
		cout << "A(const A& a)" << endl;
	}
private:
	int _a;
};

int main()
{
	A a1(1);
    //先1构造一个临时对象,在拷贝构造给a2,最终vs编译器优化为直接用1构造a2
	A a2 = 1; //本质是有个隐式类型转换,int->A
	return 0;
}

二,static成员

声明为static的类成员,称为类的静态成员:

  • 用static修饰的成员变量,称为静态成员变量;
  • 用static修饰的成员函数,称为静态成员函数;

特性:

  • 静态成员为所有类对象所共享,不属于每个具体的实列;
  • 静态成员变量必须在类外定义,定义时不添加static关键字;
  • 类静态成员访问,即可用类名::静态成员,也可对象.静态成员;
  • 静态成员函数,没有隐藏的this指针,不能访问任何非静态成员变量或非静态成员函数;
  • 静态成员和类的普通成员一样,也有public、private、protected,也可具有返回值;
​
class A
{
public:
	int _a;
    //静态成员变量
	static int _count;
};
//需类外定义,且无需static关键字
int A::_count = 1;

int main()
{
	A a;
    //访问形式
	A::_count;
	a._count;
	return 0;
}

​
class A
{
public:
	void print()
	{
		cout << "print" << endl;
	}
    //静态成员函数
	static int Get()
	{
		//print(); 不可调用
		return _count;
	}
private:
	int _a;
	static int _count;
};

int A::_count = 1;

int main()
{
	A a;
    //访问形式
    A::Get();
	a.Get();
	return 0;
}

三,C++11的成员初始化新玩法

        C++11支持非静态成员变量,在声明时进行初始化赋值,但要注意这里不是初始化,是给声明的成员变量缺省值;

class A
{
public:
	A(int a = 0)
	{
		_a = a;
	}
private:
	int _a = 10;
};

class B
{
private:
    //非静态成员变量,可在成员声明时给缺省值
	int _b = 20;
    int* p = (int*)malloc(sizeof(int)*10);
	A _a = 20; //单参数,有个隐式转换
    //静态成员不在构造函数初始化,要在类外定义初始化
    //static int _n = 10;
};

四,友元

        友元提供了一种突破封装的方式,但友元会增加耦合度,破坏了封装,所以友元不宜多用;

分类:

  • 友元函数
  • 友元类

友元函数

        可直接访问类的私有成员,是定义在类外部的普通函数,不属于任何类,但需要在类的内部声明;声明时加friend关键字;

  • 友元函数可访问类的私有和保护成员,但不是类的成员函数;
  • 友元函数不能用const修饰;
  • 友元函数可在类定义的任何地方声明,不受类访问限定符限制;
  • 一个函数可以有多个类的友元函数;
  • 友元函数的调用与普通函数的调用原理相同;
class A
{
    //友元函数
	friend void print(const A& a);
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a = 10;
};
//类外定义的普通函数,需类内部声明且添加fiend关键字
void print(const A& a)
{
	cout << a._a << endl;
}

int main()
{
	A a(1);
	print(a);
	return 0;
}
class B; //前置声明
class A
{
	friend void print(const A& a, const B& b);
public:
	A(int a)
		:_a(a)
	{}
private:
	int _a = 10;
};

class B
{
	friend void print(const A& a, const B& b);
public:
	B(int b)
		:_b(b)
	{}
private:
	int _b = 10;
};
//一个函数可以有多个类的友元函数
void print(const A& a, const B& b)
{
	cout << a._a << endl;
	cout << b._b << endl;
}

int main()
{
	A a(1);
	B b(2);
	print(a, b);
	return 0;
}

友元类

        友元类的所有成员函数都可以是另一个类的友元函数,都可以访问另一个类中的非公有成员;

  • 友元关系是单向的,不具有交换性;
  • 友元关系不能传递;
class A
{
	friend class B;
private:
	int _a = 10;
};

class B
{
public:
	void print(const A& a)
	{
		cout << a._a << endl;
	}
private:
	int _b = 20;
};

int main()
{
	A a;
	B b;
	b.print(a);
	return 0;
}

五,内部类

        如一个类定义在另一个类的内部,此内部的类就叫做内部类;此时这个内部类是一个独立的类,不属于外部类,更不能通过外部类的对象去调用内部类;外部类对内部类没有任何优越的访问权限;

        内部类就是外部类的友元类;注意友元类的定义,内部类可通过外部类的对象参数访问外部类中的所有成员,但外部类不是内部类的友元;

特性:

  • 内部类可以定义在外部类的public、private、protected,都是可以的;
  • 注意内部类可以直接访问外部类中的static、枚举成员,不需要外部类的对象/类名;
  • sizeof(外部类) = 外部类,和内部类没有任何关系;
class A
{
private:
	int _a = 10;
	
public:
	class B
	{
	public:
		//内部类,天生是A的友元
		void print(const A& a)
		{
			cout << a._a << endl;
		}
	private:
		int _b = 20;
	};
};

int main()
{
	A a;
	//受外部类类域即访问限定符限制
	A::B b; 
	b.print(a);
	return 0;
}

这篇关于C++初阶 —— 类与对象(三)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!