c++ 中的函数查找

template <class T>
class visibility
{
public:
  void say(double d){};

private:
  void say(int i){};

  void say(T t){};

};

int _tmain(int argc, _TCHAR* argv[])
{
  visibility<char*> v;
  v.say(123);    // error C2248: ‘visibility<T>::say‘ : cannot access private member declared in class ‘visibility<T>‘
             // 重载决议后: void say(int i){};

  v.say("123");    // error C2248: ‘visibility<T>::say‘ : cannot access private member declared in class ‘visibility<T>‘
               // 重载决议后: void say(T t){};

  return 0;
}

0 访问限制:

1 private:   它的名字只能被所声明的类的成员和友元使用。
2 protected: 它的名字可以被所声明的类的成员和友元使用,也可以被派生类的成员和友元使用
3 public:    它的名字可以无限制的用在任何地方。

1 发生在调用之前

cpp文件中调用的一个函数(或成员函数),编译器主要做了下面四件事情:

1).Name lookup(名字查找)

确定一系列的候选者。(注意所谓 ‘名字查找‘ 中的 ‘名字‘ 仅仅是函数名, 而不是函数签名, 即不包括返回值, 参数)

(1) 范围查找, 范围一旦确定下来, 就停止范围查找.

  a) 如果有限定名 (X::func), 则在X::中查找; 找不到就 error;

  b) 如果是成员函数(object->func), 则在类中查找, 找不到,再去基类中查找; 找不到就 error;

   c) 如果形如 `func()` 的函数, 查找规则如下:

<c-1> 外层函数(调用者)所在类中查找; 找不到就到 <c-2>;

<c-2> 基类中查找, 找不到再去外层基类中查找(baseclass -> 外层的 baseclass -> ...); 一旦找到就停止查找; 找不到就到 <c-3>;

eg: void A::say() {  func(); } 去say 所在的类A中找, 找不到再去A的基类中找。

    <c-3> 在当前的namespace 中查找; 找不到再去外层 namespace 中查找(当前的 namespace-> 外层的 namespace -> 更外层的 namespace....) ; 一旦找到就停止查找; 找不到就 error;

    注意: 如果函数参数是 class/struct, 那么由于koening 查询, 参数类型所在的 namespace 也会被列为查找范围。所以参数类型所在的 namespace 中的名字也会被列入到候选范围。

        eg: 这里在 namespace Lv2 中找到了 ‘func‘, 通过 koening 在 koeningNs 中也找到了 ‘func‘,  所以 (III) 查找到的候选者有: { (I) koeningNs::func , (II) Lv3::Lv2::func }

namespace koeningNs
{
    class KCls {};
    void func(KCls){}                  // (I)
}
namespace Lv3{
    namespace Lv2    {
        void func(koeningNs::KCls){ }  // (II)
        namespace Lv1
        {
            class myCls
            {
            public :
                void say()
                {
                    func(koeningNs::KCls()); // (III)
                                   // error C2668: ‘Lv3::Lv2::func‘ : ambiguous call to overloaded function
                }
            };
        }
    }
}
void test_nn()
{
    Lv3::Lv2::Lv1::myCls obj;
    obj.say();
};

   <c-4> 最后确定候选者们 : { 类中的候选者们 } or { 基类中的候选者们 } or { namespace 中的候选者们}

       注意 : 一旦编译器确定了一个候选者集合, 就停止查找。比如 : 找到了 { 类中的候选者们 }, 那么就不会再关注 { 基类中的候选者们 } 更会不关注 { namespace 中的候选者们}。

(2) 在找到的范围中, 确定一系列候选者

  比如: 在class 中找到了say, 那么可以确定候选者:

   void say(double d);

   void say(int i);

2.Overload resolution(重载决议)

  编译器开始执行重载决议, 根据参数最匹配原则,从候选者中选出最匹配的函数。如不唯一,就存在二义性。

  eg: int say(int i) 被选中.

   优先级:

  1) 非模板函数

  2) 如果编译器没有发现合适的非模板函数, 那么主函数模板被纳入考虑.

函数模板特化并不参与重载决议.只有在某个主模板被重载的决议前提下,其特化版本才有可能被使用,而且编译器在选择主模板的时候并不关心他是否有某个特化版本.

因为函数特化模板不参与重载决议, 所以, 如果想运用某个函数的特化, 最好的方法是重载该函数。

3.Accessibility checking(可访问性检测).

  编译器执行可访问性检测来决定被选中的函数是否能被调用。

  重载决议发生在可访问性检查之前. 因此,如果私有函数不幸参与了重载,并且被选中,最终也会出现无法访问的编译提示.

  这常常隐含二义性,这样的设计本身也不合理.换句话说,私有参数,在名字查找和重载时并非是私有的.

注意, 针对模板函数, 这个阶段只检测主模板函数, 而不会管模板函数的特化形式。也就是说如果无法访问主模板函数, 即使模板函数的特化版本是public, 也没用。

4. 如果选中的是模板函数, 那么还要进行模版特化决议

class CTemp
{
public:
    template <typename T>
    void sayHello()
    {
        cout << " sayHello : 主模板" << endl;
    }
private:
    template <>
    void sayHello<int>()
    {
        cout << "sayHello : 特化模板" << endl;
    }
private:
    template <typename T>
    void sayBonjour()
    {
        cout << " sayBonjour : 主模板" << endl;
    }
public:
    template <>
    void sayBonjour<int>()
    {
        cout << " sayBonjour : 特化板" << endl;
    }
};
void test_nn()
{
    CTemp ct;
    ct.sayHello<int>();   // 主模板 public, 特化模板 private
                          // 可以调用特化的 private.
    ct.sayBonjour<int>(); // error C2248: ‘CTemp::sayBonjour‘ : cannot access private member declared in class ‘CTemp‘
                          // 主模板 private, 特化模板 public
                          // 主模板在 ‘可访问性检查‘ 的时候就被认为 ‘不可访问‘, 即使特化模板 public 也不行。
};
时间: 2024-10-13 07:56:46

c++ 中的函数查找的相关文章

c#中的字符串查找函数

indexOf()方法,查找某字符串在一个字符串内的位置,没有则返回-1string aa="abcdef";int a=aa.indexOf("bc");//a会等于1int b=aa.indexOf("a");//b会等于0int c=aa.indexOf("g");c会等于-1所以你只要判断返回出来的int值是不是小于0就知道这个字符串里有没有包含指定的另一个字符串 c#中的字符串查找函数,布布扣,bubuko.com

【图文】Excel中vlookup函数的使用方法

今天统计数据,用到了Excel中vlookup函数,第一次使用当然少不了百度,经过反复研究后,算是解决了问题,现整理成文档. 一.实现效果 Sheet1 Sheet2   注:上图中sheet1商品条码列(即D列)引用sheet2中商品条码(即B列)中的数据 二.vlookup函数调用说明 以sheet1中调用函数为例,如下: =VLOOKUP(A2,Sheet2!$A$2:$B$100,2,TRUE) 函数中共有四个调用参数 1)  第一个参数:A2 :可任意指定,也可以是B2.C2等.这一列

模板中的名字查找问题

问题起源 先看下面很简单的一小段程序. `#include <iostream>` template <typename T> struct Base { void fun() { std::cout << "Base::fun" << std::endl; } }; template <typename T> struct Derived : Base<T> { void gun() { std::cout &l

Makefile中的函数

Makefile 中的函数 Makefile 中自带了一些函数, 利用这些函数可以简化 Makefile 的编写. 函数调用语法如下: $(<function> <arguments>) # 或者 ${<function> <arguments>} <function> 是函数名 <arguments> 是函数参数 1.1 字符串函数 字符串替换函数: $(subst <from>,<to>,<text&

STL中的二分查找———lower_bound,upper_bound,binary_search

关于STL中的排序和检索,排序一般用sort函数即可,今天来整理一下检索中常用的函数——lower_bound , upper_bound 和 binary_search . STL中关于二分查找的函数有三个lower_bound .upper_bound .binary_search .这三个函数都运用于有序区间(当然这也是运用二分查找的前提). Tips:1.在检索前,应该用sort函数对数组进行从小到大排序.     2.使用以上函数时必须包含头文件:#include < algorith

C++中lower_bound函数和upper_bound函数

STL中关于二分查找的函数有三个lower_bound .upper_bound .binary_search .这三个函数都运用于有序区间(当然这也是运用二分查找的前提),下面记录一下这两个函数. ForwardIter lower_bound(ForwardIter first, ForwardIter last,const _Tp& val)算法返回一个非递减序列[first, last)中的第一个大于等于值val的位置. ForwardIter upper_bound(ForwardIt

文件系统中的目录查找

Linux中的一个进程在识别一个文件的时候,将文件名传递给VFS层,VFS要根据文件名查找这个文件的索引节点inode,以备后续对该文件的操作.通过文件名查找文件索引节点的过程就叫做路径查找(path lookup).本文是在阅读目录查找代码时随手记录的笔记,会在不断的学习中不断补充. 路径查找的起始阶段,内核会从某一个特定的dentry开始查起,如果路径名是以‘/’开始,则起始的dentry是current->fs->root:否则,起始的dentry是current->fs->

《python源码剖析》笔记 python虚拟机中的函数机制

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.Python虚拟机在执行函数调用时会动态地创建新的 PyFrameObject对象, 这些PyFrameObject对象之间会形成PyFrameObject对象链,模拟x86平台上运行时栈 2.PyFuctionObject对象 typedef struct { PyObject_HEAD PyObject *func_code: //对应函数编译后的PyCodeObject对象 Py

mysql中find_in_set()函数的使用

首先举个例子来说: 有个文章表里面有个type字段,它存储的是文章类型,有 1头条.2推荐.3热点.4图文等等 .现在有篇文章他既是头条,又是热点,还是图文,type中以 1,3,4 的格式存储.那我们如何用sql查找所有type中有4的图文类型的文章呢?? 这就要我们的 find_in_set 出马的时候到了.以下为引用的内容: select * from article where FIND_IN_SET('4',type) ---------------------------------