【问题标题】:How to call base class overloaded func using derived class instance,如何使用派生类实例调用基类重载函数,
【发布时间】:2013-07-07 13:06:14
【问题描述】:

我试图了解派生类是否重载了基类 func,(基类具有 int 参数,der 类具有 double 参数)当我创建 der 类实例并使用正确参数调用 func 名称时,仅调用 der func ??有人可以帮助我吗.. 代码的第 28 行有没有办法 (dd.f(d1);) ,我可以获得基类 func 调用。

这里是代码。

using namespace std;

class base {

    public :

        virtual void f (int i);

};

class der : public base{

    public:

        void f ( double d);

};

void base::f(int i){

    cout << "Base::f \n";

}

void der::f(double d){

    cout <<"Der::f \n";

}

int main(){

    der dd;

    int i =99;

    double d1 = 3232.232;

    dd.f(i); // why this calls der class func???

    dd.f(d1);

    base *ptr = new der();

    ptr->f(i);

    dynamic_cast<der *>(ptr)->f(d1);

    return 0;
}

【问题讨论】:

  • 编译器不会在多个范围内搜索重载。它在类层次结构中找到“f(...)”的第一个版本并停在那里。然后它将搜索该类并且仅搜索该类的重载。它发现 der::f(double) 作为重载,隐式转换为从 int 到 double 并使用它。你可以把“使用 base::f;”在 "der" 中得到你想要的行为。

标签: c++ inheritance


【解决方案1】:

当你在派生类中声明与基类同名的函数时,基类中的函数会被隐藏。

解决方案

`use base::f`

#include <iostream>
using namespace std;

class base {     
public :
    virtual void f (int i); 
};

class der : public base{
public:
    using base::f;
    void f ( double d);
};

void base::f(int i){
    cout << "Base::f \n";
}

void der::f(double d){
    cout <<"Der::f \n";
}

int main(){
    der dd;
    int i =99;     
    dd.f(i); // Base::f

    return 0;
}

推理

class Base {
    virtual void store(long l){
        //both int and long could be processed
    }
}

你创建派生类

class Derived {
    virtual void store(long l) {
        //store another way.
    }
}

and call it like 

Derived d;
d.store(1);

然后有人认为“我可以更快地存储整数!”并创建

Base::store(int)

如果没有这样的隐藏,你就失败了

【讨论】:

    【解决方案2】:

    我不是 C++ 程序员,但我相当确定该语言可以识别由传递给它的参数调用的函数/方法以及名称。 f(int) 与 f(double) 不同。搜索一下多态性

    【讨论】:

    • 根据您的解释,应该调用基类的方法。问题是为什么不调用它。
    【解决方案3】:

    为什么这会调用 der 类函数???

    因为编译器仅在同一类中声明的函数之间通过签名选择函数。例如,如果你有这样的事情:

    class der : public base{
    
    public:
        void f ( double d);
        void f (int i ){cout << "f(int)" <<endl;}
    };
    

    调用您的dd.f(i); 会将您带到输出f(int)

    由于你的der类有一个函数f()虽然调用参数不匹配,编译器不需要去base类,它只是将你的int转换为@987654328 @

    为了从base 类中显式调用f(),您可以这样做:dd.base::f(i);

    【讨论】:

    • “编译器不需要转到基类” - 比这稍差。编译器不会转到基类,即使它有需要。尝试将“f(int)”更改为“f(std::string)”,然后将其称为“der.f(std::string())”而不是“der.f(i)”。它不会编译,因为它不能将 std::string 转换为 double。这个程序只能编译,因为 C++ 会自动将 int 转换为 double。
    • @JoshG79 是的,只有在派生类中没有(同名)的情况下,编译器才会尝试在基类中找到合适的函数。
    • 感谢您的帮助,之前知道范围解析运算符。但没想到:)
    • 是的,即使我尝试使用字符串参数调用 func f 并且即使在基类中正确声明了 func 也失败了。但是正如 RiaD 建议在 der 类中添加“使用 base::f”一样,这个问题也得到了解决。我不知道如果您在 der 类中重载 func,那么基类 func 将被隐藏。有什么好学的。感谢大家分享信息并参与讨论。干杯
    【解决方案4】:

    以下称为覆盖

    class baseClass
    {
    public:
        virtual void DoIt()
        {//.........
        }
    }
    class child : public baseClass
    {
        void DoIt()
        {
            baseClass::DoIt();
        }
    }
    

    在 Microsoft Visual C++ 中 您可以使用 _super 代替基类名称 _super::DoIt()

    您所做的不是覆盖它,而是另一种具有不同签名的方法,如果有问题只是在您的类的公共主体中使用 using base::confusingMethod; 如下所示。

    class base
    {
    public:
        base(){}
        virtual void Job(int x)
        {
            cout<<"Base"<<endl;
        }
    };
    class son : public base
    {
    public:
        using base::Job;
        son(){}
        virtual void Job(float x)
        {
            cout<<"Son"<<endl;
        }
    };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-21
      • 2012-04-16
      • 2019-07-25
      • 2019-07-16
      • 1970-01-01
      • 2016-07-06
      • 2018-11-14
      • 2015-12-30
      相关资源
      最近更新 更多