龙空技术网

C++基础语法梳理:友元类和友元函数以及using用法

C语言编程 236

前言:

现在朋友们对“c语言using”可能比较注重,兄弟们都想要了解一些“c语言using”的相关知识。那么小编同时在网上网罗了一些对于“c语言using””的相关知识,希望同学们能喜欢,大家一起来了解一下吧!

本期是C++基础语法分享的第五节,今天给大家来分享一下:

(1)explicit(显式)关键字;

(2)friend 友元类和友元函数;

(3)using;

(4):: 范围解析运算符;

(5)enum 枚举类型;

(6)decltype;

那么我们接下来一起来看看吧!

explicit(显式)关键字

explicit 修饰构造函数时,可以防止隐式转换和复制初始化

explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外

explicit 使用

struct A{	A(int) { }	operator bool() const { return true; }};struct B{	explicit B(int) {}	explicit operator bool() const { return true; }};void doA(A a) {}void doB(B b) {}int main(){	A a1(1);		// OK:直接初始化	A a2 = 1;		// OK:复制初始化	A a3{ 1 };		// OK:直接列表初始化	A a4 = { 1 };		// OK:复制列表初始化	A a5 = (A)1;		// OK:允许 static_cast 的显式转换 	doA(1);			// OK:允许从 int 到 A 的隐式转换	if (a1);		// OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换	bool a6(a1);		// OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换	bool a7 = a1;		// OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换	bool a8 = static_cast<bool>(a1);  // OK :static_cast 进行直接初始化	B b1(1);		// OK:直接初始化	B b2 = 1;		// 错误:被 explicit 修饰构造函数的对象不可以复制初始化	B b3{ 1 };		// OK:直接列表初始化	B b4 = { 1 };		// 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化	B b5 = (B)1;		// OK:允许 static_cast 的显式转换	doB(1);			// 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换	if (b1);		// OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换	bool b6(b1);		// OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换	bool b7 = b1;		// 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换	bool b8 = static_cast<bool>(b1);  // OK:static_cast 进行直接初始化	return 0;}
friend 友元类和友元函数

能访问私有成员

破坏封装性

友元关系不可传递

友元关系的单向性

友元声明的形式及数量不受限制

using

using 声明

一条 using 声明 语句一次只引入命名空间的一个成员。它使得我们可以清楚知道程序中所引用的到底是哪个名字。如:

using namespace_name::name;

构造函数的 using 声明

在 C++11 中,派生类能够重用其直接基类定义的构造函数。

class Derived : Base {public:    using Base::Base;    /* ... */};

如上 using 声明,对于基类的每个构造函数,编译器都生成一个与之对应(形参列表完全相同)的派生类构造函数。生成如下类型构造函数:

Derived(parms) : Base(args) { }

using 指示

using 指示 使得某个特定命名空间中所有名字都可见,这样我们就无需再为它们添加任何前缀限定符了。如:

using namespace_name name;

尽量少使用 using 指示 污染命名空间

一般说来,使用 using 命令比使用 using 编译命令更安全,这是由于它只导入了指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。

using 使用

尽量少使用 using 指示

using namespace std;

应该多使用 using 声明

int x;std::cin >> x ;std::cout << x << std::endl;

或者

using std::cin;using std::cout;using std::endl;int x;cin >> x;cout << x << endl;
:: 范围解析运算符

分类

全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间

类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的

命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的

:: 使用

int count = 11;         // 全局(::)的 countclass A {public:	static int count;   // 类 A 的 count(A::count)};int A::count = 21;void fun(){	int count = 31;     // 初始化局部的 count 为 31	count = 32;         // 设置局部的 count 的值为 32}int main() {	::count = 12;       // 测试 1:设置全局的 count 的值为 12	A::count = 22;      // 测试 2:设置类 A 的 count 为 22	fun();		        // 测试 3	return 0;}
enum 枚举类型

限定作用域的枚举类型

enum class open_modes { input, output, append };

不限定作用域的枚举类型

enum color { red, yellow, green };enum { floatPrec = 6, doublePrec = 10 };
decltype

decltype 关键字用于检查实体的声明类型或表达式的类型及值分类。语法:

decltype ( expression )

decltype 使用

// 尾置返回允许我们在参数列表之后声明返回类型template <typename It>auto fcn(It beg, It end) -> decltype(*beg){    // 处理序列    return *beg;    // 返回序列中一个元素的引用}// 为了使用模板参数成员,必须用 typenametemplate <typename It>auto fcn2(It beg, It end) -> typename remove_reference<decltype(*beg)>::type{    // 处理序列    return *beg;    // 返回序列中一个元素的拷贝}

今天的分享就到这里了,大家要好好学C++哟~

写在最后:对于准备学习C/C++编程的小伙伴,如果你想更好的提升你的编程核心能力(内功)不妨从现在开始!

编程学习书籍分享:

编程学习视频分享:

整理分享(多年学习的源码、项目实战视频、项目笔记,基础入门教程)

欢迎转行和学习编程的伙伴,利用更多的资料学习成长比自己琢磨更快哦!

对于C/C++感兴趣可以关注小编在后台私信我:【编程交流】一起来学习哦!可以领取一些C/C++的项目学习视频资料哦!已经设置好了关键词自动回复,自动领取就好了!

标签: #c语言using #友元函数可以直接访问类的所有成员吗 #友元函数是成员函数在其中能直接访问私有成员 #友元函数调用 #友元函数调用方法