在实现中没有看到的虚方法

时间:2009-09-04 07:22:35

标签: c++ virtual-inheritance

我目前正在开发一个C ++项目,我有一个稍后实现的抽象接口。该接口还有一个实现的方法,我的实现不会覆盖。 我的问题是,在使用我的实现时,编译器(MSVC)没有看到接口方法。是什么导致这种情况,我该如何解决?

这是代码。

#include <string>
#include <vector>
using std::string;

class A
{
    public:
    string name;
};

class interface
{ 
public:
    virtual int num_foo() = 0;
    virtual A* foo(int) = 0;
    virtual A* foo(string &name){
        for ( int i(0); i < num_foo(); i++)
            if ( foo(i)->name == name )
                return foo(i);
        return 0;
    }
};

class implementation : public interface
{
public:
    virtual int num_foo() { return m_foos.size(); }
    virtual A* foo(int i) { 
        //check range 
        return &m_foos[i];
    }
    std::vector<A> m_foos;
};

int main(...)
{
    implementation impl;
    // impl is properly initialized here

    string name( "bar" );
    // here comes my problem, the MSVC compiler doesn't see foo(string &name)
    // and gives an error
    A *a = impl.foo( name );
}

4 个答案:

答案 0 :(得分:5)

名称解析在重载解析之前发生。在impl.foo( name )中,编译器查看implementation类并仅查找virtual A& foo(int i)。它没有查看基类,因为它找到了一个具有正确名称的函数。

要更正此用法,可以向派生类添加using interface::foo声明,以便将foo的所有基本版本拉入派生类,以便进行重载解析。通常,我更愿意避免重载函数,我可能会给出foo个不同函数名的变体。

(其他错误是您没有定义stringvectorm_ones;您尝试在引用上使用->代替.并且您尝试在返回对A的引用的函数中返回0。)

答案 1 :(得分:3)

要在子类中重新发布基本方法(例如foo(string))以进行重载,请添加

  using interface::foo;

进入类实现。

答案 2 :(得分:1)

class implementation : public interface{
    public:
       using interface::foo;
       int num_foo() { return m_foos.size(); }
       A& foo(int i)
       {   //check range
           return m_ones[i];
       }
       vector<A> m_foos;
       vector<A> m_ones;
};

答案 3 :(得分:0)

这只是一个问题,因为您正在访问implementation接口,该接口有foo成员,正如@ charles-bailey在回答中所述。

从语义上讲,你试图调用的是interface方法foo,所以你可能应该实际调用它:

int main()
{
    implementation impl;
    string name( "bar" );
    interface& interf = impl;
    A *a = interf.foo( name );
    A *b = interf.foo( 4 );
}

通过将implementation::foo设为私有,您还可以实施Non-Virtual Interface idiom。如果你试图直接调用impl.foo,你仍然会失败,但是你的所有参数类型都会失败,并且会出现同样的错误。

(我知道这个问题已经过时了,但NVI已经老了......)