博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
图为先C++笔试20131017
阅读量:6897 次
发布时间:2019-06-27

本文共 3061 字,大约阅读时间需要 10 分钟。

hot3.png

标识符

extern

置于变量或函数前,以表示变量或函数的定义在别的文件中,提示编译器遇见此变量和函数时在其他模块中寻找其定义。在使用extern时候要严格对应声明时的格式。

在一个源文件里定义了一个数组:char a[6];
在另外一个文件里用下列语句进行了声明:extern char *a;
不可以,程序运行时会告诉你非法访问。原因在于,指向类型T的指针
并不等价于类型T的数组
。extern char *a声明的是一个指针
变量而不是字符数组
,因此与实际的定义不同,从而造成运行时非法访问。应该将声明改为extern char a[ ]。

现代编译器一般采用按文件编译的方式,因此在编译时,各个文件中定义的全局变量是互相不透明的。也就是说,在编译时,全局变量的可见域限制在文件内部。

extern “C”
在C++环境下使用C函数的时候,常常会出现编译器无法找到obj模块中的C函数定义,从而导致链接失败的情况,应该如何解决这种情况呢?

答案与分析:

C++语言在编译的时候为了解决函数的多态问题,会将函数名和参数联合起来生成一个中间的函数名称,而C语言则不会,因此会造成链接时找不到对应函数情况,此时C函数就需要用extern “C”进行链接指定,这告诉编译器,请保持我的名称,不要给我生成用于链接的中间函数名。

#pragma

预处理指令,设定的状态或者是指示编译器完成一些特定的动作

#pragma message(“消息文本”)

当 遇到这条指令时就在编译输出窗口中将消息文本打印出来。

获取结构体偏移量

这个宏定义在C标准库的头文件 stddef.h 里有定义
typedef unsigned long size_t;
#define offsetof(TYPE, MEMBER) ((size_t)  &((TYPE *)0)->MEMBER)
#include 
using namespace std; struct test{ int a; int b; char c; int d;};#define FIND(structTest,e) (size_t) &(((structTest*)0)->e)int main(){ size_t s = FIND(test,b); //test t; cout<
<
>c; return 0;}

4、隐式转换

 第一种:classB: public A {

}

B公有继承A,可以是间接公有继承,当把B的对象赋值给A,会发生隐式转换。

待求证,保护继承、私有继承、BA的成员能否发生转换?

 第二种:

classB:{

OperatorA();

.

}

转换constructor。类B实现了隐式转化为类Acompiler会在需要的时候自动调用该函数发生类型转换,如果想要在代码中显式的调用转换函数才能发生类型转化,可以定义explicit operator A()

第三种:

class A{

const B &

}

A实现了一个个non-explicit的构造函数,参数为B(还可以带其他的有缺省值的参数)

第四种:A&operator =(const B & 

注意:对于类之间的公有继承总可以把子类转化为父类,只是把派生类对象切割为基类对象即可。

注意2上述第二种和第三种方法同时存在一个程序中,应该注意这样的调用:

fconst A &);

B b;

f(b)则会产生调用的二义性。

注意3如果不想使用隐式生成的函数(当然这些函数一般是缺省构造函数、copy构造函数和赋值构造函数),就要把它显式的禁止;对于一般的转换constructor可以添加explicit明确的要求显式的调用,compiler不能自动发生隐式转换。如:

Private

A &operator = (const B &;

A (const A & );

按照默认规定,只有一个参数的构造函数也定义了一个隐式转换,将该构造函数对应数据类型的数据转换为该类对象,如下面所示:

class String {
String ( const char* p ); 
// 用C风格的字符串p作为初始化值
//…
}
String s1 = “hello”; //OK 隐式转换,等价于String s1 = String(“hello”);
 
但是有的时候可能会不需要这种隐式转换,如下:
class String {
       String ( int n ); //本意是预先分配n个字节给字符串
       String ( const char* p ); 
// 用C风格的字符串p作为初始化值
//…
}
下面两种写法比较正常:
String s2 ( 10 );   //OK 分配10个字节的空字符串
String s3 = String ( 10 ); //OK 分配10个字节的空字符串
下面两种写法就比较疑惑了:
String s4 = 10; //编译通过,也是分配10个字节的空字符串
String s5 = ‘a’; //编译通过,分配int(‘a’)个字节的空字符串
 
s4 和s5 分别把一个int型和char型,隐式转换成了分配若干字节的空字符串,容易令人误解。
为了避免这种错误的发生,我们可以声明显示的转换,使用
explicit 关键字:
class String {
       
explicit String ( int n ); //本意是预先分配n个字节给字符串
       String ( const char* p ); 
// 用C风格的字符串p作为初始化值
//…
}
加上
explicit
就抑制了String ( int n )的隐式转换,
 
下面两种写法仍然正确:
String s2 ( 10 );   //OK 分配10个字节的空字符串
String s3 = String ( 10 ); //OK 分配10个字节的空字符串
 
下面两种写法就不允许了:
String s4 = 10; //编译不通过,不允许隐式的转换
String s5 = ‘a’; //编译不通过,不允许隐式的转换
 
因此,某些时候,
explicit 可以有效得防止构造函数的隐式转换带来的错误或者误解
----------------------------------------------------------
explicit   只对构造函数起作用,用来抑制隐式转换。如:   
  class   A   {   
          A(int   a);   
  };   
  int   Function(A   a);   
    
  当调用   Function(2)   的时候,2   会隐式转换为   A   类型。这种情况常常不是程序员想要的结果,所以,要避免之,就可以这样写:   
    
  class   A   {   
          explicit   A(int   a);   
  };   
  int   Function(A   a);   
    
  这样,当调用   Function(2)   的时候,编译器会给出错误信息(除非   Function   有个以   int   为参数的重载形式),这就避免了在程序员毫不知情的情况下出现错误。
总结:
explicit   只对构造函数起作用,用来抑制隐式转换。

转载于:https://my.oschina.net/u/347414/blog/169751

你可能感兴趣的文章
我的Android进阶之旅------&gt;关于使用Android Studio替换App的launcher图标之后仍然显示默认的ic_launcher图标的解决方法...
查看>>
Linux下GPIO驱动
查看>>
C#中各种计时器 Stopwatch、TimeSpan
查看>>
我的Java开发学习之旅------&gt;解惑Java进行三目运算时的自动类型转换
查看>>
mybatis 使用经验小结
查看>>
linux下磁盘相关工具(待整理)
查看>>
为什么你的路由器穿墙能力差?看完秒懂
查看>>
漫谈数据库索引
查看>>
RTP与RTCP协议介绍
查看>>
这家创业公司,为什么会在云栖大会上被反复提及?
查看>>
如何使用Unhook技术绕过安全软件的防护?
查看>>
运营商5G服务开跑?你不要被骗了!
查看>>
WCF后续之旅(4):WCF Extension Point 概览
查看>>
Alibaba Cloud and UK Met Office to Co-organise Tianchi Data Mining Contest
查看>>
SCALA表达示简例
查看>>
现代数据中心如何满足超高速互联的全球经济的需要?
查看>>
AI 如何保障校园安全?安防“老大”海康威视是这么做的
查看>>
【阿里云资讯】如何让云计算安全变得更“聪明”
查看>>
[LeetCode]--12. Integer to Roman
查看>>
阿里巴巴 江苏总部将落户南京
查看>>