class A
{
virtual void Test(void*)
{
}
};

class B : public A
{
virtual void Test(void*, void*)
{
}
};

void main()
{
B test;
test.Test(0);
}

this code doesn't compile:
test.cpp(18) : error C2660: 'B::Test' : function does not take 1 arguments

Why?

Test(void*) is a member of the base class of B, so why the compiler can't
find it?

Thank you very much.

--
Alessandro Vergani

Re: function lookup by SvenC

SvenC
Mon Jun 25 03:00:51 CDT 2007

Hi Alessando,

> class A
> {

public: // I guess you missed public by accident?

> virtual void Test(void*);
> };
>
> class B : public A
> {

public: // I guess you missed public by accident?

> virtual void Test(void*, void*);
> };
>
> void main()
> {
> B test;
> test.Test(0);
> }
>
> this code doesn't compile:
> test.cpp(18) : error C2660: 'B::Test' : function does not take 1 arguments
> Why?
>
> Test(void*) is a member of the base class of B, so why the compiler
> can't find it?

When you introduce a member with the same name as a base member then you
hide the base member.
You need to explicitly introduce it in the sub class with a using statement:

class B : public A
{
public:
using A::Test;
virtual void Test(void*, void*);
};

--
SvenC


Re: function lookup by Stuart

Stuart
Mon Jun 25 03:08:34 CDT 2007

Alessandro Vergani wrote:
> class A
> {
> virtual void Test(void*)
> {
> }
> };
>
> class B : public A
> {
> virtual void Test(void*, void*)
> {
> }
> };
>
> void main()
> {
> B test;
> test.Test(0);
> }
>
> this code doesn't compile:
> test.cpp(18) : error C2660: 'B::Test' : function does not take 1 arguments
>
> Why?
>
> Test(void*) is a member of the base class of B, so why the compiler
> can't find it?

Congratulations, you've tripped over one of the less obvious obstacles of C++:
If you add an overloaded version of a base class method, the base class method
is "hidden" by that new method (I can't image why this is considered a valuable
feature of the C++ language). If you want to expose the base class method from
the derived class as well, you have to add an using-statement to your derived class:

class B : public A
{
using A::Test;
virtual void Test(void*, void*)
{
}
};

BTW, since you didn't specify any access modifiers, you won't be able to invoke
Test on your object, but you probably just wanted to see the right compilation
error.

Regards,
Stuart

Re: function lookup by Alessandro

Alessandro
Mon Jun 25 03:32:16 CDT 2007

On Mon, 25 Jun 2007 10:00:51 +0200, SvenC <SvenC@community.nospam> wrote:

Hi Sven,

> public: // I guess you missed public by accident?

You guessed right.

> When you introduce a member with the same name as a base member then you
> hide the base member.
> You need to explicitly introduce it in the sub class with a using
> statement:
>
> class B : public A
> {
> public:
> using A::Test;
> virtual void Test(void*, void*);
> };

Thank you very much (and thank to Stuart too)

--
Alessandro Vergani

Re: function lookup by Doug

Doug
Mon Jun 25 05:57:59 CDT 2007

On Mon, 25 Jun 2007 09:48:58 +0200, "Alessandro Vergani"
<avergani@insignis.it> wrote:

>class A
>{
> virtual void Test(void*)
> {
> }
>};
>
>class B : public A
>{
> virtual void Test(void*, void*)
> {
> }
>};
>
>void main()
>{
> B test;
> test.Test(0);
>}
>
>this code doesn't compile:
>test.cpp(18) : error C2660: 'B::Test' : function does not take 1 arguments
>
>Why?
>
>Test(void*) is a member of the base class of B, so why the compiler can't
>find it?
>
>Thank you very much.

Overloading doesn't span scopes. The function B::Test has a different
signature from A::Test and thus doesn't override it. Instead, because
overloading doesn't span scopes, it is said to hide A::Test. I wouldn't
necessarily recommend it, but you can bring the declaration of A::Test into
B with a using-declaration:

class B : public A
{
using A::Test;

virtual void Test(void*, void*)
{
}
};

Then your example will work. That said, it's usually best to avoid
overloading virtual functions, because a derived class that overrides fewer
than all of them hides the rest. It would be somewhat weird to only need to
override some of them, and usually, you can define a set of non-virtual
overloads and one (typically protected) virtual function they all defer to.

--
Doug Harrison
Visual C++ MVP

Re: function lookup by Igor

Igor
Mon Jun 25 07:30:55 CDT 2007

"Stuart Redmann" <DerTopper@web.de> wrote in message
news:f5o0dk$9u1$1@news.dtag.de
> Congratulations, you've tripped over one of the less obvious
> obstacles of C++: If you add an overloaded version of a base class
> method, the base
> class method is "hidden" by that new method (I can't image why this is
> considered
> a valuable feature of the C++ language).

The guiding design principle here is that "invisible" changes should not
silently alter the meaning of the problem - they should either have no
effect, or fail with an error. In particular, adding a new method to a
base class should not silently alter the behavior of the derived class,
unless the latter explicitly opts in (with the using directive).
Consider:

class B {
public:
// void f(int); // (1)
};

class D {
public:
void f(long);
};

D d;
d.f(1); // (2) - calls D::f()

If C++ didn't have the rule in question, then uncommenting line (1)
would make line (2) call B::f instead (as a better match). This is
precisely the silent change of meaning the rule is intended to prevent.
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going to
land, and it could be dangerous sitting under them as they fly
overhead. -- RFC 1925



Re: function lookup by Larry

Larry
Mon Jun 25 09:17:24 CDT 2007

> Congratulations, you've tripped over one of the less obvious obstacles of
> C++: If you add an overloaded version of a base class method, the base
> class method is "hidden" by that new method (I can't image why this is
> considered a valuable feature of the C++ language).

Expanding on what Igor said, what about the case where the base class member
and derived class member share the same name but are otherwise unrelated.
The wrong overload can kick in. Unrelated or not, the problem becomes even
more dangerous if someone adds the overload later on which only reinforces
Igor's point. Imagine adding a base class function "f()" a year later
without any knowledge of derived class function "f()". Your call to the
derived class version might now start calling the base class version and you
might not even know it until it's on your customer's machine. You could then
have a very serious and hard-to-find error on your hands. The language
therefore forces you to be explicit about things by relying on the "using"
statement to bring all overloads into a common scope.