17

It must be something specific in my code, which I can't post. But maybe someone can suggest possible causes.

Basically I have:

class CParent
{
 public:
  void doIt(int x);
};
class CChild : public CParent
{
 public:
  void doIt(int x,int y,int z);
};

CChild *pChild = ...
pChild->doIt(123); //FAILS compiler, no method found
CParent *pParent = pChild;
pParent->doIt(123); //works fine

How on earth?

EDIT: people are talking about shadowing/hiding. But the two versions of doIt have different numbers of parameters. Surely that can't confuse the compiler, overloads in child class which can't possibly be confused with the parent class version? Can it?

The compiler error I get is: error C2660: 'CChild::doIt' : function does not take 1 argument

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589

7 Answers7

34

You have shadowed a method. For example:

struct base
{
    void method(int);
    void method(float);
};

struct derived : base
{
    void method(int);
    // base::method(int) is not visible.
    // base::method(float) is not visible.
};

You can fix this with a using directive:

class derived : public base
{
    using base::method; // bring all of them in.

    void method(int);
    // base::method(int) is not visible.
    // base::method(float) is visible.
};

Since you seem insistent about the number of parameters, I'll address that. That doesn't change anything. Observe:

struct base
{
    void method(int){}
};

struct derived : base
{
    void method(int,int){}
    // method(int) is not visible.
};

struct derived_fixed : base
{
    using base::method;
    void method(int,int){}
};

int main(void)
{
    {
        derived d;

        d.method(1, 2); // will compile
        d.method(3); // will NOT compile
    }
    {
        derived_fixed d;

        d.method(1, 2); // will compile
        d.method(3); // will compile
    }
}

It will still be shadowed regardless of parameters or return types; it's simply the name that shadows. using base::<x>; will bring all of base's "<x>" methods into visibility.

GManNickG
  • 494,350
  • 52
  • 494
  • 543
  • Awesome, I didn't think I'd still be discovering weird and whack C++ features. – Igor Zevaka Jan 14 '10 at 22:55
  • 2
    The using directive will not bring all of the base class' methods into visibility. Well, in this case yes, but in general. It will bring all the methods with the name mentioned in the using directive into visibility. It's nit-picky of me, yes. But it's an important distinction. – Omnifarious Jan 14 '10 at 23:18
  • For the first code snippet, `base::method(int)` is still not visible in the scope of `derived` even after the using declaration, because `derived` has a function with the same name and parameter types. (Notice this is a using *declaration*, not a using *directive* - the latter is the `using namespace ...` thing, which is unrelated). – Johannes Schaub - litb Jan 15 '10 at 12:25
3

You are hitting a classic problem. You need using CParent::doIt; in your CChild class. I'll scrounge up the duplicate questions.

Edit:

Here's my answer to essentially the same question: Overriding a Base's Overloaded Function in C++

Community
  • 1
  • 1
Fred Larson
  • 60,987
  • 18
  • 112
  • 174
  • What? The overload in the child class has different parameters to the parent class. Why would it be a problem? – Mr. Boy Jan 14 '10 at 22:49
  • Read the linked answer. I think it will explain things. – Fred Larson Jan 14 '10 at 22:50
  • All the examples posted are for overloads with same argument count. I can see those would confuse compiler. But when it sees doit(123), and finds doIt(x,y,z), why would it treat this as a match and stop looking? – Mr. Boy Jan 14 '10 at 22:58
  • No, it's a name match. Once the name matches, it doesn't bother looking for other overloads higher in the hierarchy. Just try `using` and it'll work. – Fred Larson Jan 14 '10 at 23:02
1

I have never done this without having that method in the base class before. I think that adding "using CLASS::METHOD" in derived class will give you access to the other version of the overloaded method.

class CParent
{
 public:
  void doIt(int x);
};
class CChild : public CParent
{
 public:
  void doIt(int x,int y,int z);

  using CParent::doIt;
};
mholzmann
  • 1,289
  • 1
  • 8
  • 4
0

The problem is CChild doesn't actually inherit from CParent.

And so it doesn't have a doIt method that takes only one argument.

Anon.
  • 58,739
  • 8
  • 81
  • 86
0

When you override a function in the derived class, only that function in the derived class is visible to the user of that class. The base class version becomes hidden.

Therefore, your pChild pointer calling doIt(int x) will fail since you are using a derived class pointer to call the base class function. The pParent pointer calling doIt(int x) will work since you are using a base class pointer to call the base class function. Even though you have a child object being pointed to by a parent pointer (upcasted), the class type here is determined by the declaration of the pointer which is a CParent.

To be able to call that base class function using the derived class pointer, you can:

  1. Qualify the base class name in the function call, as in the following:

    pChild->CParent::doIt(123);

  2. Use a using directive to bring the function name from the base class into the derived class, as seen in the previous posts.

jasonline
  • 8,646
  • 19
  • 59
  • 80
0

I understand that this behavior is to give you flexibility to override the behavior of base class method in your derived class.

Lets assume that you have a function foo(int) in base class and you want to change the behavior of this function in your derived class. Now if the base class method is not hidden by your derived class method (which has same prototype as that of base class's method), it will introduce ambiguity in overload resolution.

mukeshkumar
  • 2,698
  • 3
  • 19
  • 20
-2

The method in your child class has a different number of arguments than what you're trying to pass into it. Could it be related to that?

Jeff Barger
  • 1,241
  • 1
  • 13
  • 19