为什么要使用“ using”关键字来访问我的基类方法?


75

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

为什么编译器以这种方式运行?还是我做错了什么?

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;
}

请告诉我:如果您在“ const char how”中删除const怎么办?
帕维尔·拉兹维洛夫斯基

31
您无需输入Son s = Son();。那只是创建一个临时文件,然后调用复制构造函数。正义打字Son s;
Charles Salvia


Answers:


63

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

然后,该方法与调用的参数不匹配,您将得到一个错误。

另请参阅C ++常见问题解答,以获取有关此主题的更多说明。


9
@sth很高兴知道这一点。但是,我可以说这是C ++的功能还是某种错误?这不会破坏整个继承观念吗?只是问..
Sumudu

名称匹配是使用整齐的名称完成的,方法重载在这里起作用吗?还是第一个调用的名称为“ action”的函数就这样了?
tmaric

4
@Anubis:该规则简化了名称查找。没有它,编译器在需要解析成员函数的名称时将需要遍历完整的继承树(某些基类中的函数可能会重载)。使用该规则,编译器一旦发现包含合适名称的类,就可以停止查看继承树的其余部分。程序员处于相同的情况。通过查看派生类,他可以确定在那里定义的函数将被调用,而不必知道某个基类是否可能包含同名的其他函数。
2013年

18

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

请参阅C ++常见问题解答


6

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

一种可能性:

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

6

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.