0

:I have the following scenario:

// NOTE:  pseudo example only, sorry for the early typos
class Foo
{
  public:
     virtual bool IsItSo();
     virtual bool IsItSo(string x);
};

bool Foo::IsItSo()
{
  return true;
}

class Bar : Foo
{
   public:
     // not here
     virtual bool IsItSo(string x);
};

bool Bar::IsItSo(string x)
{
   return (x == "")
}

class Helper
{
   public:
     void HelperMethod();
};

void Helper::HelperMethod()
{
   Bar *p = new Bar
   // ... hack hack hack
   bool b = p->IsItSo();    //<-- compilation error
}

The specific error I get is:

file.cpp(1124) : error C2660: 'Bar::IsItSo' : function does not take 0 arguments

Could someone explain this magical-madness to me?

MrDuk
  • 16,578
  • 18
  • 74
  • 133

2 Answers2

3

Overriding works on functions with the same signature, but this is actually a red herring here.

Things is, member functions in derived class hide member functions in the base class that have the same name (regardless of the signature). The fact that your functions are virtual doesn't matter here, as you don't attempt dynamic dispatch anywhere.

If you wrote:

Foo* f = new Bar;
f->IsItSo();

it would work, as it would f->IsItSo("Oi"); (and it would call the function from the derived class).

Name lookup starts looking in static type of the object (in your case, it is Bar) and stops looking when it encounters the name. The only IsItSo that's visible from Bar is the one that takes a std::string parameter.

jrok
  • 54,456
  • 9
  • 109
  • 141
  • ...unless you bring them into the scope of the derived class with `using`. – Bathsheba Jan 09 '14 at 13:36
  • @Bathsheba: Or rather, Say What You Mean and have `Foo *p = new Bar;`. – Kerrek SB Jan 09 '14 at 13:37
  • I changed my answer as I think the original version wasn't really correct. – jrok Jan 09 '14 at 13:41
  • With `using` can you specify a specific signature? I.e., can I only scope the one with no parameters, but keep the polymorphic behavior of the ones that *do* have parameters? – MrDuk Jan 09 '14 at 14:02
1

You need to dynamic cast the pointer to the base class if you want to use that method

class Foo
{
  public:
     virtual bool IsItSo();
     virtual bool IsItSo(string x);
};

bool Foo::IsItSo()
{
  return true;
}

class Bar : public Foo
{
   public:
     // not here
     virtual bool IsItSo(string x);
};

bool Bar::IsItSo(string x)
{
   return (x == "");
}

int main()
{
    Bar *p = new Bar();

    Foo* p_converted = dynamic_cast<Foo*>(p);
    bool b = p_converted->IsItSo();

    return 0;
}

otherwise the base class will have overloaded methods hidden by the overridden one in the derived class (lookup stops in the first scope where a name is resolved)

Marco A.
  • 43,032
  • 26
  • 132
  • 246