【问题标题】:Why should I use the "using" keyword to access my base class method?为什么要使用“using”关键字来访问我的基类方法?
【发布时间】:2010-12-26 04:37:21
【问题描述】:

我编写了以下代码来解释我的问题。如果我注释第 11 行(使用关键字“using”),编译器不会编译该文件并显示此错误:invalid conversion from 'char' to 'const char*'。在Son 类中似乎没有看到Parent 类的方法void action(char)

为什么编译器会这样?还是我做错了什么?

class Parent
{
    public:
        virtual void action( const char how ){ this->action( &how ); }
        virtual void action( const char * how ) = 0;
};

class Son : public Parent
{
    public:
        using Parent::action; // Why should i write this line?
        void action( const char * how ){ printf( "Action: %c\n", *how ); }
};

int main( int argc, char** argv )
{
    Son s = Son();
    s.action( 'a' );
    return 0;
}

【问题讨论】:

标签: c++ oop inheritance using


【解决方案1】:

派生类中声明的action隐藏了基类中声明的action。如果您在Son 对象上使用action,编译器将搜索Son 中声明的方法,找到一个名为action 的方法,然后使用它。它不会继续搜索基类的方法,因为它已经找到了匹配的名称。

然后那个方法与调用的参数不匹配,你会得到一个错误。

有关此主题的更多说明,另请参阅C++ FAQ

【讨论】:

  • @sth 很高兴知道这一点。但是,我可以说,这是 c++ 的一个特性还是某种错误?这不是破坏了继承的整个想法吗?只是问..
  • 是使用重载名称完成名称匹配,方法重载在这里起作用,还是第一个调用的函数具有名称“action”,仅此而已?
  • @Anubis:该规则简化了名称查找。没有它,编译器在需要解析成员函数的名称时需要遍历完整的继承树(在某些基类中可能存在函数的重载)。使用该规则,编译器可以在找到包含合适名称的类后停止查看继承树的其余部分。程序员处于同样的境地。查看派生类,他可以确定将调用那里定义的函数,而不必知道某个基类是否可能包含同名的不同函数。
【解决方案2】:

令人惊讶的是,这是标准行为。如果派生类声明了与基类定义的方法同名的方法,派生类的方法会隐藏基类的方法。

C++ FAQ

【讨论】:

    【解决方案3】:

    注意事项:在这种情况下需要使用“使用”是一个危险信号,表明您的代码可能会让其他开发人员感到困惑(毕竟它让编译器感到困惑!)。您可能应该重命名这两种方法中的一种,以便让其他程序员清楚区分。

    一种可能性:

    void action( const char how )
    { 
      takeAction( &how ); 
    }
    void action( const char * how )
    {
      takeAction(how);
    }
    virtual void takeAction(const char * how) = 0;
    

    【讨论】:

      【解决方案4】:

      如果在派生类中重新定义任何重载函数,则隐藏基类中的所有重载函数。 包含这两种功能的一种方法是避免类中的函数重载。要么 您可以使用 using 关键字。

      【讨论】:

      • 我有一个包含大量方法的基类,每个方法都使用base::method 编写很乏味。有没有办法使用单个 using 声明来做到这一点?
      【解决方案5】:

      通过使用using,将基类中声明的名称引入派生类的命名空间中。

      然后,当您在派生类中声明这组函数时,编译器通过隐式this 指针的类型将它们与其基类中具有相同参数类型的函数区分开来。

      在重载决策期间,需要进行类类型转换的参数(当指向派生类的指针转换为指向基类的指针时会发生这种情况)的优先级最低。

      因此可以区分具有看似相同的参数列表的两个函数,并且当从派生类型的对象调用它们时,本地声明的将是更好的(如果不是精确的)匹配。

      我是新手,请指出我的误解。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-11
        • 1970-01-01
        • 2013-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-10
        相关资源
        最近更新 更多