图为先C++笔试20131017

标识符

extern

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

在一个源文件里定义了一个数组: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

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

#pragma message(“消息文本”)

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

获取结构体偏移量 code

这个宏定义在C标准库的头文件 stddef.h 里有定义
typedef unsigned long size_t;
#define offsetof(TYPE, MEMBER) ((size_t)  &((TYPE *)0)->MEMBER)
#include <iostream>

 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<<s<<endl;

    char c;
    cin>>c;
    return 0;
}

四、隐式转换 htm

 第一种: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   只对构造函数起做用,用来抑制隐式转换。
相关文章
相关标签/搜索