波奇学C++:&重载,初始化列表,explicit, static

默认成员函数除了:构造函数,析构函数,拷贝构造函数,运算符重载还有&符重载

默认成员都不能在类外定义,会默认生成。

&重载函数

A* operator&()
{
   return this;
}
const A* operator&()const
{
   return  this;
}
//const 类实例和 普通实例都能调用。

&重载一般无特别大的意义,可以用来隐藏地址。此时&地址会返回空指针。

A* operator&()
{
   return nullptr;
}
const A* operator&()const
{
   return  nullptr;
}

初始化列表

class object
{
private:
	int _aa = 1;
};
class A
{
public:
	A()
		: _a(1)
		, _b (_a)
		, _c(1)
		,aa()
	{}
private:
	int _a;
	int& _b;
	const int _c;
	object aa;
	
};

初始化列表以冒号开始,间隔逗号。

初始化列表和构造函数体赋值都能用来初始化变量,初始列表可以用来初始化一些构造函数体不能赋值的变量。引用,const对象,自定义类型只能在初始化列表中初始化。

原因:引用,const 对象都必须在定义时初始化,而初始化列表相当于就是定义的地方,所以能进行初始化,函数体赋值更像时对初始化列表的2次修改。

那private 的变量不是定义吗?缺省值不是定义了吗?

不是,在private 相当于变量声明,缺省值相当于在初始化列表定义时,传入的值。所以,其实初始化列表始终存在,且先调用初始化列表,再调用函数体赋值。

三者的关系可以如下显示

int a;//private中声明
int a=1;//初始化列表
a=2;//函数体赋值

初始化列表可以替代函数体完成大部分工作,但还是需要函数体,如开辟动态内存后检测指针合法。推荐使用初始化列表初始化。

自定义类型为什么要在初始化列表中初始化?

因为如果编译器在定义自定义类型时无初始化就会报错,本质上和const对像一致。

自定义初始化类型的特性:初始化顺序和声明顺序保持一致

class A
{
public:
	A()
		: _a(1)
		, _b (_a)
		, _c(1)
	{
		
	}
private:
	int& _b;
	int _a;
	const int _c;
	object aa;
	
};

b的值是随机值,因为b的声明在a前,所以初始化列表先调用b的初始化,而忽略a=1;

explicit关键字来阻止隐式转换

class object
{
public:
	object(int a)
	{
		_aa = a;
	}
private:
	int _aa=1;
};
//调用
object a1(1);
object a2=1;

object a1(1)是初始化,那么object a2=1是发生隐式转换

object a2=1->int转换为类隐式转换,产生临时变量,临时变量再调用拷贝构造初始化a2

object a2=1-> const object x(1)->object a2(x);

编译对这个过程进行优化,当一个表达式有多个构造时,编译器直接省略拷贝构造调用构造函数。

相当于object a2(1) ,不调用拷贝构造

证明存在临时变量:

object& b1 =1;
const object& b2=2;

第一行报错,第二行可以,说明存在临时变量,存在拷贝构造。

如果存在多个成员变量

class object
{
public:
	object(int a = 1,int b=2)
	{
		_a = a;
		_b = b;
		cout << _a << _b << endl;
	}
	void fun2()
	{
		;
	}
private:
	int _a;
	int _b;
};
object a = 3;
//结果为32
object a=3,4;//报错

隐式转换也只能初始化第一个成员变量。所以用隐式转换来代替构造,只能用于初始化一个成员变量时。

通过在构造函数前加explicit来阻止隐式转换。

class object
{
public:
	explicit object(int a)
	{
		_aa = a;
	}
private:
	int _aa=1;
};
//调用
object a2=1;
//结果报错

类的static静态成员

静态成员变量

class object
{
public:
	object(int a)
	{
		_aa = a;
	}
private:
	int _aa=1;
    static int a;
};
//调用
object a1(1);
object a2=1;
//全局定义
int object :: a=0;

类定义静态变量是对全局变量的优化,类里面的静态变量只会定义有一次构造一次 。

类里面定义静态变量,成员变量属于每个类对象,静态变量属于每个类对象共享。不能在初始化列表初始化。

类的初始化只能在类外,定义在全局。

int object::a = 0;//定义时不要加static

静态变量依然受访问限定符限制,private和public的区别。

静态变量的运用场景:

统计实例个数时:在析构--,拷贝构造和构造函数++

静态成员函数

class object
{
public:
	object(int a)
	{
		_aa = a;
	}
    static void fun1()
	{
		;
	}
	void fun2()
	{
		;
	}
private:
	int _aa=1;
    static int a;
};

静态成员函数:fun1()在函数前加入static。fun2()不是静态成员函数。

静态成员函数特点,函数调用时不会传入this指针,这意味着不能在静态函数中调用非静态函数和非静态成员变量,但可以调用静态成员变量

static fun1()
{
    fun2();
    cout<< _aa<<endl;//报错
    cout<<a<<endl;//可运行
    
}//报错

但是可以在非静态成员函数中调用静态成员函数。

 fun2()
{
    fun1();
}//可以使用

在类外可以用类名或者对象名访问静态函数。既然不需要this指针就能访问,所以可以用类名访问。

int main()
{
    object a;
    a.fun();
    object.fun();
}

静态成员依然受范围限定符的限制。

静态函数的使用场景:只允许创建栈上的类

思路:把构造函数放在private中,创建一个public的静态函数返回创建的实例。这样才没有实例的情况下也能调用构造函数创造实例。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值