隐式类型转换、static成员、匿名对象

 

一、隐式类型转换

1、转换的类型:

隐式类型转换:意义相似的类型(如:int与double可以,string和vector不行)
显式的强制类型转换:int与int*
自定义类型:单参数构造函数支持隐式类型转换。

#include<iostream>
using namespace std;
class A
{
public:
    A(int a)
        :_a(a)
    {
        cout << "A(int a)" << endl;
    }

    A(const A& aa)
        :_a(aa._a)
    {
        cout << "A(const A& aa)" << endl;
    }

//禁止隐式类型转换
//  explicit A(int a)
//		:_a(a)
//	{
//		cout << "A(int a)" << endl;
//	}
	

private:
    int _a;
};

int main()
{
    A aa1(1);
    A aa2 = 2;//隐式类型转换(整形转换为自定义类型)
    //2构造了一个A的临时对象,临时对象再拷贝构造aa2-->优化用2直接构造

    int i = 10;
    double d = i;

    const A& aa3 = 2;//隐式类型转换会产生临时变量,临时变量具有常性
 
    return 0;
}

 volatile修饰的变量,每次都要去内存取:

int main()
{
	// volatile 修饰的变量,每次都要去内存取,否则经过编译器优化后去寄存器取
	volatile const int n = 10;
	// 转换有安全隐患的
	int* p = (int*)&n;
	(*p)++;

	cout << n << endl;
	cout << *p << endl;

	cout << p << endl;//虚拟地址

	return 0;
}

2、C++强制类型转换:
标准C++为了加强类型转换的可视性,引入了四种命名的强制类型转换操作符:static_cast、reinterpret_cast、const_cast、dynamic_cast。

①static_cast:用于非多态类型的转换(静态转换),但它不能用于两个不相关的类型进行转换。
②reinterpret_cast:用于将一种类型转换为另一种不同的类型(为操作数的位模式提供较低层次的重新解释)。
③const_cast:删除变量的const属性,方便赋值。

int main()
{
	// 相关类型/相近类型
	double d = 12.34;
	int a = static_cast<int>(d);
	cout << a << endl;

	// 不相关类型
	int* p1 = &a;
	int address = reinterpret_cast<int>(p1);

	// 去掉const属性
	volatile const int n = 10;
	int* p2 = const_cast<int*>(&n);

	return 0;
}

④dynamic_cast:用于将一个父类对象的指针/引用转换为子类对象的指针或引用(动态转换)
向上转型:子类对象指针/引用->父类指针/引用(不需要转换,赋值兼容规则)
向下转型:父类对象指针/引用->子类指针/引用(用dynamic_cast转型是安全的)
注意:
1. dynamic_cast只能用于父类含有虚函数的类
2. dynamic_cast会先检查是否能转换成功,能成功则转换,不能则返回0

class A
{
public:
	virtual void f() {}

	int _x = 0;
};

class B : public A
{
public:
	int _y = 0;
};

void fun(A* pa)
{
	// pa是指向子类对象B的,转换可以成功,正常返回地址
	// pa是指向父类对象A的,转换失败,返回空指针
	B* pb = dynamic_cast<B*>(pa);
	if (pb)
	{
		cout << "转换成功" << endl;
		pb->_x++;
		pb->_y++;
	}
	else
	{
		cout << "转换失败" << endl;
	}
}

int main()
{
	A aa;
	fun(&aa);

	B bb;
	fun(&bb);

	return 0;
}

二、static成员

//实验
#include<iostream>
using namespace std;

int _scount = 0;

class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	~A() { --_scount; }
private:
};

A aa0;

A Func(A aa1)
{
	cout << __LINE__ << ":" << _scount << endl;//打印 21:4
	return aa1;
}

int main()
{
	cout << __LINE__ << ":" << _scount << endl;//打印 29:1
	A aa1;
	static A aa2;
	Func(aa1);
	cout << __LINE__ << ":" << _scount << endl;//打印 33:3
	return 0;
}

 · 成员变量属于每个类对象,存储在对象里。
   静态成员变量,属于类,属于类的每个对象共享,存储在静态区。需要在全局位置,类外面定       义。(突破一次私有)
 · 静态成员,没有this指针(不能访问非静态成员),只要突破/指定类域和访问限定符/友元,就       可以访问。
 · 静态成员函数和静态成员变量配套出现。
 · 静态成员变量不能给缺省值(因为他没有初始化列表)(缺省值是给初始化列表的)。
 · 静态成员在类里面声明,类外面定义,且不受访问限定符的限制。
 · 静态不可以调用非静态(非静态的成员函数调用需要this指针,而静态没有),非静态可以调用     静态

#include<iostream>
using namespace std;

class A
{
public:
	A() { ++_scount; }
	A(const A& t) { ++_scount; }
	~A() { --_scount; }

	void Func1()
	{
		// 非静态能否调用静态:可以
		GetACount();
	}

	void Func2()
	{
		++_a1;
	}

	// 没有this指针,指定类域和访问限定符就可以访问
	static int GetACount() 
	{ 
		// 静态能否调用非静态:不可以。非静态的成员函数调用需要this指针,而静态的成员函数没有this指针
		// Func2();
		return _scount;
	}
private:
	// 成员变量 -- 属于每个一个类对象,存储对象里面
	int _a1 = 1;
	int _a2 = 2;
//public:
	// 静态成员变量 -- 属于类,属于类的每个对象共享,存储在静态区
	static int _scount;
};

// 全局位置,类外面定义
int A::_scount = 0;

A aa0;

void Func()
{
	static A aa2;
	cout << __LINE__ << ":" << aa2.GetACount() << endl;// 3

	// 全局变量的劣势:任何地方都可以随意改变
	//_scount++;
}

int main()
{
	cout <<__LINE__<<":"<< A::GetACount() << endl;  // 1
	A aa1;
	Func();  // 3
	return 0;
}
//设计一个类,在类外面只能在栈和堆上创建对象
#include<iostream>
using namespace std;

class A
{
public:
	static A GetStackObj()
	{
		A aa;
		return aa;
	}

	static A* GetHeapObj()
	{
		return new A;
	}
private:
	A()
	{}

private:
	int _a1 = 1;
	int _a2 = 2;
};

int main()
{
	//static A aa1;   //  静态区
	//A aa2;          //  栈 
	//A* ptr = new A; //  堆
	A::GetStackObj();
	A::GetHeapObj();
	return 0;
}

三、匿名对象

 · 有名对象--生命周期在当前函数局部域。
   匿名对象--生命周期在当前行,即用即销毁。

 · 匿名对象具有常性(和临时对象一样)。
   引用需加const,Const引用延长匿名对象的生命周期,生命周期在当前函数局部域。

#include<iostream>
using namespace std;

class A
{
public:
    A(int a = 0)
        :_a(a)
    {
        cout << "A(int a)" << endl;
    }

    ~A()
    {
        cout << "~A()" << endl;
    }
private:
    int _a;
};

class Solution {
public:
    int Sum_Solution(int n) {
        cout << "Sum_Solution" << endl;
        //...
        return n;
    }
};


void push_back(const string& s)
{
    cout << "push_back:" << s << endl;
}

int main()
{
    A aa(1);  // 有名对象 -- 生命周期在当前函数局部域
    A(2);     // 匿名对象 -- 生命周期在当前行

    Solution sl;
    sl.Sum_Solution(10);
    //Solution s1();//不能这么定义,因为无法区分是对象还是函数名

    Solution().Sum_Solution(20);
    //不能这样调用,因为匿名对象不包含this指针(只能调没有this指针的静态成员函数)

    //A& ra = A(1);  // 匿名对象具有常性
    const A& ra = A(1); // const引用延长匿名对象的生命周期,生命周期在当前函数局部域

    //string str("11111");
    //push_back(str);
    //push_back(string("222222"));

    push_back("222222");//匿名对象的应用

    return 0;
}

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值