c++11-14(二)关键字(enum和enum class、explicit、namespace、noexcept、nullptr)

enum

传统使用方法

enum Color { red , green, blue  };

void testOldEnum() {
	Color r = red;
	switch (r) {
	case red:
		std::cout << "i'm red\n";
		break;
	case green:
		std::cout << "i'm green\n";
		break;
	case blue:
		std::cout << "i'm blue\n";
		break;
	default:
		std::cout << "what?\n";
	}
	//enum可以直接赋值给一个整型
	int a = r;
}

这会导致一个问题,如果再定义一个enum

enum Hate{red, good, blue};

编译器好会报错。因为两个enum中都有red。有重复,就会让编译器分不清。这就会导致你引用的库里面如果使用了enum,你就不能写含有重复元素的enum

 

 

enum class

cpp 11对enum进行的扩展

//long long 用来说明enum class的大小是long long那么大
//如果不写,默认用int大小来代表enum class
enum class NewColor : long long { Red, Green = 20, Blue };

void testNewEnum() {
	NewColor r = NewColor::Blue;
	switch (r) {
	case NewColor::Red:
		std::cout << "red\n";
		break;
	case NewColor::Green:
		std::cout << "green\n";
		break;
	case NewColor::Blue:
		std::cout << "blue\n";
		break;
	}
	//enum class不能直接赋值给int类型。需要进行static_cast强制转换
	int a = static_cast<int>(r);
}

 

enum class还可以用于函数传参

之前说过,用bool类型传参,会降低代码的可读性,如果没有文档辅助,可能会引起别人对代码含有的无解。因此可以用enum class来进行函数参数传递

enum class IsGood {
	Yes,
	No
};
enum class IsHero {
	Yes,
	No
};
enum class IsMom{
	Yes,
	No
};

void show(IsGood, IsHero, IsMom) {

}

void show(bool isGood, bool isHero, bool isMom) {
	
}

 

 

 

explicit——阻止隐式转换

struct A {
  A(int) {}
  A(int, int) {}
  //使得A可以默认的转换成int
  operator int() const { return 0; }
};

struct B {
  explicit B(int) {}
  explicit B(int, int) {}
  explicit operator int() const { return 0; }
};

void handleA(A a) {}

void handleB(B b) {}

void testS(const std::string& s) {}

void testExpl() {
	A a1 = 1;        // 等价于 A a1 = A(1);
	// B b1 = 1;     //B不能那么写,因为explicit阻止编译

	A a2(2);
	B b2(2);         // OK

	A a3 = { 4, 5 };   // 等价于 A a3 = A(4,5); A{4,5};
	//B b3 = {4,5};  // 这样的不允许的

	int na1 = a1;    // OK,因为operator int() const { return 0; }
	//int nb1 = b2;  //无法通过编译

	int na2 = static_cast<int>(a1);  //显示转换,可以的
	int nb2 = static_cast<int>(b2);  //显示转换,可以的

	A a4 = (A)1;       //ok
	B b4 = (B)1;       //ok,这是强转,明确告诉编译器要转,所以可以

	handleA(a1);       //ok
	handleA(1);        //可以编译通过,因为A可以通过int构造出来
	handleB(b2);       //ok
	//handleB(2);      //编译失败

}

 

 

 

namespace

namespace XGroup {
	class A {int value;};
}

namespace YGroup {
	class A {int value;};
	class B {};
}

class A {
	int value;
	A() { throw 1;}
};

void testNamespace() {
	XGroup::A a;
	YGroup::A b;
	A c;
}

void testNamespace2() {
	namespace CGroup = XGroup;
	CGroup::A a;
	using YGroup::B;    //简化namespace前缀
	B b;
	YGroup::A aa;
	using namespace YGroup;  //直接把YGroup的全都拿来用,不过容易造成歧义
	A c;
}

 

namespace可以没有名字

//namespace可以没有名字
//astring只在当前文件中有效
namespace {
	std::string astring("long");
}

 

 

 

noexcept

告知编译器我们不会抛出异常,用以方便编译器做出一些优化处理

void f() noexcept {}

如果声明了noexcept的函数抛出了异常(比如函数里面声明一个A的对象a,a在构造的时候抛出了异常,导致函数抛出异常),此时会调用函数terminate(),用以退出函数,进而导致程序挂掉。

 

设置noexcept失效的方法

void f() noexcept(false) {}

 

 

 

nullptr

template<typename T, typename U>
void func(T t, U u) {
	t(u);
}

void nullPointer(int* a) {
	std::cout << "i'm a pointer\n";
}

void testNullPointer() {
	nullPointer(0);              //ok——0可以转化成一个指针,c++中0可以转化成一个指针
	nullPointer(NULL);           //ok——c中null是(void*)0  /c++中null是0
	nullPointer(nullptr);

	func(nullPointer, nullptr);  //ok
        //c中可以,cpp的模板对于类型检查更为严格
	func(nullPointer, 0);        //不可以,因此会把0推到成int,所以不可以
	func(nullPointer, NULL);     //不可以
	func(nullPointer, (int*)0);  //可以
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值