凌云窟
南山巅上火麟烈,北海潜深雪饮寒。可怜两锋未缘见,雪刀封隐孤剑鸣。
<2006年12月>
262728293012
3456789
10111213141516
17181920212223
24252627282930
31123456

留言簿(0)

随笔分类

随笔档案

文章档案

相册

简历下载

搜索

最新评论

  • 1. re: 很遗憾,minix的阅读计划被我取消了
  • 你可以去死了。
  • --smartly
  • 2. re: 透明文本、位图的实现方案
  • 双缓冲的确不是画在父窗口,之所以透明,是因为内存dc背景为父窗口背景.
  • --yaowei
  • 3. re: 终于启动minix源代码阅读计划了!
  • 我基本上把MINIX3主要的东西看完了。我的BLOG上有两篇文章是关于MINIX3的。有空可以交流。
    http://jnxnj.spaces.live.com
  • --k
  • 4. re: 很遗憾,minix的阅读计划被我取消了
  • 如果是迫于工作压力可以理解,一个人的精力毕竟有限。学MINIX关键是学其中的思想。MINIX3当然没有LINUX成熟,minix3 连分页都没有,关于线程的概念也没有,等等。但是,将MINIX3作为微内核的代表来看,你会发现学了是一个不小的收获。
  • --k
  • 5. 欢迎交流minix3
  • 我在chinaunix上的BLOG
    devahb.cublog.cn
  • --JEFF
  • 6. re: 构造函数调用虚函数追踪
  • vc资料站:http://www.vcmsdn.com/     对学习很有帮助的,可以上去

    看看,或加群46138350,里面有高手可以请教的。
  • --maggie
  • 7. re: x86是满递减堆栈还是空递减堆栈?
  • vc资料站:http://www.vcmsdn.com/     对学习很有帮助的,可以上去

    看看,或加群46138350,里面有高手可以请教的。
  • --maggie
  • 8. re: x86是满递减堆栈还是空递减堆栈?
  • x8086汇编基础课程中的push/pop,有详细介绍。。。。
    注:debug/release下的对应汇编有的存在差异(eg:switch/call),用release中的listfile输出.asm文件~
  • --windowssky
  • 9. re: 构造函数调用虚函数追踪
  • 赞同你的意见,当时这么想是因为看过一本书,那里说在构造函数就要设置好虚函数表,所以自然就想在构造函数中既然虚函数表已经设定好了,那有可能调用虚函数是通过虚函数表来调用哦。
    当然,事实证明这种说法是错的!原因正如你所说。
  • --莫问春秋
  • 10. 没人灌,那我灌吧
  • 虚函数表的作用是什么?
    因为对象的动态类型是什么,必须到运行时才知道,也就是只有到运行到那一步时,才知道应该实际调用哪个virtual函数。

    但在构造函数中,需要到运行时才能知道吗?它本身的类型就是其动态类型,所以根本不需要去查虚函数表。
  • --周星星

阅读排行榜

评论排行榜

 
VC知识库BLOG   首页  新随笔  联系  聚合  登录 
  随笔-22 文章-0 评论-36 Trackbacks-0

1。符号查找(对于函数此时只看名字,不看参数)
    大致顺序是
    (1)如果有限定名( XXX:: )那么就直接在XXX里查找
    (2)函数局部名字空间
    (3)(如果是成员)类名字空间
    (4)递归向上至所有基类的名字空间
    (5)当前名字空间
    (6)递归向外至所有外层名字空间,
    在任一层里, 用using导入的符号和该层的其他符号同一对待。
    keonig查找: 对于函数, 如果参数为类/结构/模版类并位于其他的名字空间,
    在(5)和(6)的查找中导入该空间(不递归向外)的符号一同查找.

2。(如果是函数)重载决议(注意此时特化的函数不参与决议)

3。(如果是类内部的名字)检查访问权(注意此时特化的函数仍然不参与决议)

4。(如果找到了一个模版)模版特化决议

 

编译器执行以上步骤的时候是使用贪心匹配,只要找到一个符合当前检查内容的就会停止查

所以任何一层都有可能发生错误的掩盖情况

例1

 1 void  f( int ) {}
 2 class  Y
 3 {
 4 public :
 5      void  f() {}
 6     Y()
 7      {
 8         f( 1 );
 9     }

10 }
;


这里的f(2)在1.(2)这里找到了符号f,就不会向上到1.(5)查找到真正的f(int)了

例2

void  g( int ) {}
namespace  S
{
    
void  g() {}

    
void  h()
    
{
        g(
1 );
    }

}


这里的g(1)在1.(5)这里找到了符号g,就不会向上到1.(6)查找到真正的g(int)了

例3

class  Y
{
    
void  f( int ) {}   // [1]
public :
    
void  f( double ) {}   // [2]
}
;

int  main()
{
    Y y;
    y.f(
1 );
}


y.f(1)会调用[2]吗?不会,因为在第2步重载决议的时候就选定[1]了,因此这段代码会报
出无法访问private成员的错误

例4

template  < typename T >
void  f(T) {}   // [1]

template 
< typename T >
void  f(T * ) {}   // [2]

template 
<>
void  f < int *> ( int * ) {}   // [3]


int  main()
{
    
int   * =   0 ;
    f(p);
}


这里的f(p)会调用[3]吗?
不会,因为在进行到第二步重载决议的时候,只有[1]和[2]参与了重载决议,结果选择了
[2],那么[1]的特化版本[3]当然就轮不到了。

例5

class  X
{
    template 
< typename T >   void  g()  {}
public :
    template 
<>   void  g < int > () {}
}
;

int  main()
{
    X y;
    y.g
< int > ();
}


这里首先第3步访问检查发现g为private(此时g的特化版本被直接无视了),所以即使
g<int>为public, 该段代码仍然不能够编译通过

例6

namespace  E
{
    
class  X {} ;
    
void  f(X) {}   // [1]
}


void  f(E::X) {}    // [2]

class  X
{
public :
    
void  f() {}   // [3]
     void  g()
    
{
        E::X x;
        f(x); 
// [4]
    }

}
;

[4]会调用那个呢? 在1.(3)里就确定了是[3],因此参数不匹配
如果注释掉[3]的f,那么由于koenig查找, 在1.(5)里[1]和[2]都会是平等的可选项
所以会出现二义性.
如果把namespace E改为class E, 把E中的f改为静态函数
由于koenig查找仅仅导入参数的名字空间, 因此[1]将不参与1.(5)的查找,
最终结果会是[2]

posted on 2006-12-29 10:44 莫问春秋 阅读(2573) 评论(10)  编辑 收藏
Comments
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]