67、经典问题解析五

1、面试问题

编写程序判断一个变量是不是指针。

2、指针的判别

— C++中依然支持 C语言中的可变参数函数
— C++ 编译器的匹配调用优先级
  1、重载函数
  2、函数模板
  3、变参函数(接收任意多的参数)

#include <iostream>
using namespace std;

void test(int i)                          //优先级第一
{
	cout << "void test(int i)" << endl;
}

template <typename T>
void test(T t)                           //优先级第二
{
	cout << "void test(T t)" << endl;
}

void test(...)                           //优先级第三
{
	cout << "void test(...))" << endl;
}
int main()
{
	int i = 0;
	test(i);

	return 0;
}

注释前两个函数得出的结果:
在这里插入图片描述

  • 思路:
    — 将变量分为两类:指针和非指针
    — 编写函数:
     指针调用时返回 true;
     非指针调用时返回 false;
#include <iostream>
#include <string>
using namespace std;

class Test
{
public:
	Test()
	{
	}
	~Test()
	{
	}
};

template <typename T>
bool isPtr(T* p)
{
	return true;
}

bool isPtr(...)
{
	return false;
}
int main()
{
	int i = 0;
	int* p = &i;
	cout << "it is a pointer: " <<isPtr(p) << endl;
	cout << "it is a pointer: " << isPtr(i) << endl;
	
	Test test;
	Test* t = &test;

	cout << "it is a pointer: " << isPtr(t) << endl;
	cout << "it is a pointer: " << isPtr(test) << endl;		//变参函数是C语言中的东西

	return 0;
}

在这里插入图片描述
非法指令原因:变参函数当参数是对象的时候会出错,因为变参函数是C语言里面的东西。变参函数根本不知道对象是什么东西。

存在缺陷:
变参函数无法解析对象参数,可能造成程序崩溃

进一步的挑战:
如何让编译器精确匹配函数,但不进行实际的调用?

解决方案:sizeof

#include <iostream>
#include <string>
using namespace std;

class Test
{
public:
	Test()
	{
	}
	~Test()
	{
	}
};
template <typename T>
char isPtr(T* p)
{
	return 'c';
}

int isPtr(...)
{
	return 0;
}
#define ISPTR(p) (sizeof(isPtr(p)) == sizeof(char))
int main()
{
	int i = 0;
	int* p = &i;
	cout << "it is a pointer: " << ISPTR(p) << endl;
	cout << "it is a pointer: " << ISPTR(i) << endl;
	
	Test test;
	Test* t = &test;

	cout << "it is a pointer: " << ISPTR(t) << endl;
	cout << "it is a pointer: " << ISPTR(test) << endl;

	return 0;
}

在这里插入图片描述

2、面试问题

如果构造函数中抛出异常会发生什么情况?

  • 构造函数中抛出异常
    — 构造过程立即停止
    当前对象无法生成
    — 析构函数不会被调用
    — 对象占用的空间立即收回(重点)
  • 工程项目中的建议
    — 不要在构造函数中抛出异常
    — 当构造函数可能产生异常时,使用二阶构造模式
#include <iostream>
#include <string>
using namespace std;

class Test
{
public:
	Test()
	{
		cout << "Test()" << endl;
		throw 0;
	}
	~Test()
	{
		cout << "~Test()" << endl;
	}
};

int main()
{
	Test* p = reinterpret_cast<Test*>(1);
	try
	{
		p = new Test();
	}
	catch (...)
	{
		cout << "Exception" << endl;
	}
	
	cout << p << endl;
	return 0;
}

在这里插入图片描述
在构造函数中抛出异常的情况下,new关键字是不会返回一个地址值的,连空指针都不会返回。你可以看到这个 p 指针指向的地址还是我们开始的 1 地址处。

  • 析构中的异常
    避免在析构函数中抛出异常
    析构函数的异常将导致:对象所使用的资源无法完全释放。

小结:

  • C++中依然支持变参函数
  • 变参函数无法很好的处理对象参数
  • 利用函数模板和变参函数能够判断指针变量
  • 构造函数和析构函数中不要抛出异常
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值