Discussion:
Overloading member functions, some virtual, some not
(too old to reply)
Dave
2010-02-14 07:26:32 UTC
Permalink
Hi folks,

Got the following class hierarchy, and am getting a strange compile
error from it:

class RootFinder
{
public:
virtual ~RootFinder(){}

double findRoot( const Function1D& func, double guess ) const;
virtual double findRoot( const Function1D& func, double min, double
max ) const = 0;

private:
bool findGoodInterval( const Function1D& func, double guess, double&
min, double& max ) const;
};

class BisectionRootFinder : public RootFinder
{
public:
BisectionRootFinder(){}
virtual double findRoot( const Function1D& func, double min, double
max ) const;
};



If I then try to use the second class like so:

BisectionRootFinder rootFinder;
const double root = rootFinder.findRoot( func, guess );

I get the following compile error on that second line :

error C2660: 'BisectionRootFinder::findRoot' : function does not
take 2 arguments

I'm not sure why this is happening, as it should be able to find the
non-virtual version of findRoot(...) that is in the base class. I can
coax it to find it by doing the following:

BisectionRootFinder bisectRootFinder;
RootFinder& rootFinder = bisectRootFinder;
const double root = rootFinder.findRoot( func, guess );

and all works fine. But, why do I need to go through that extra step?
Am I declaring something wrong, or is VC just misbehaving? If it
matters, I am using Visual Studio 2008 Express (version 9.0.30729.1
SP)

Thanks.
David Lowndes
2010-02-14 10:38:53 UTC
Permalink
Post by Dave
error C2660: 'BisectionRootFinder::findRoot' : function does not
take 2 arguments
I'm not sure why this is happening, as it should be able to find the
non-virtual version of findRoot(...) that is in the base class. I can
BisectionRootFinder bisectRootFinder;
RootFinder& rootFinder = bisectRootFinder;
const double root = rootFinder.findRoot( func, guess );
and all works fine. But, why do I need to go through that extra step?
The Comeau online compiler behaves exactly the same - so I'd hazard a
guess that it's what the standard says should happen.

Dave
David Wilkinson
2010-02-14 11:09:21 UTC
Permalink
Post by Dave
Hi folks,
Got the following class hierarchy, and am getting a strange compile
class RootFinder
{
virtual ~RootFinder(){}
double findRoot( const Function1D& func, double guess ) const;
virtual double findRoot( const Function1D& func, double min, double
max ) const = 0;
bool findGoodInterval( const Function1D& func, double guess, double&
min, double& max ) const;
};
class BisectionRootFinder : public RootFinder
{
BisectionRootFinder(){}
virtual double findRoot( const Function1D& func, double min, double
max ) const;
};
BisectionRootFinder rootFinder;
const double root = rootFinder.findRoot( func, guess );
error C2660: 'BisectionRootFinder::findRoot' : function does not
take 2 arguments
I'm not sure why this is happening, as it should be able to find the
non-virtual version of findRoot(...) that is in the base class. I can
BisectionRootFinder bisectRootFinder;
RootFinder& rootFinder = bisectRootFinder;
const double root = rootFinder.findRoot( func, guess );
and all works fine. But, why do I need to go through that extra step?
Am I declaring something wrong, or is VC just misbehaving? If it
matters, I am using Visual Studio 2008 Express (version 9.0.30729.1
SP)
Them's the rules. Whne the compiler finds a matching name in
BisectionRootFinder, it will not look in the base class for a function with the
correct dignature. I used to think this was odd, but you get used to it.

It will work if you do

class BisectionRootFinder : public RootFinder
{
public:
using RootFinder::findRoot;
BisectionRootFinder(){}
virtual double findRoot( const Function1D& func, double min, double max ) const;
};

However, IMHO, this is not good style. There is really no reason to use the same
name for the two functions here.
--
David Wilkinson
Visual C++ MVP
Igor Tandetnik
2010-02-14 13:19:46 UTC
Permalink
Post by Dave
Got the following class hierarchy, and am getting a strange compile
class RootFinder
{
virtual ~RootFinder(){}
double findRoot( const Function1D& func, double guess ) const;
virtual double findRoot( const Function1D& func, double min, double
max ) const = 0;
bool findGoodInterval( const Function1D& func, double guess, double&
min, double& max ) const;
};
class BisectionRootFinder : public RootFinder
{
BisectionRootFinder(){}
virtual double findRoot( const Function1D& func, double min, double
max ) const;
};
David Wilkinson explained why this doesn't work (a method in a derived class hides all methods with the same name in the base class). This is how I'd deal with it:

class RootFinder
{
public:
virtual ~RootFinder(){}

double findRoot( const Function1D& func, double guess ) const;
double findRoot( const Function1D& func, double min,
double max ) const;

private:
virtual double doFindRoot( const Function1D& func, double min, double
max ) const = 0;
};

class BisectionRootFinder : public RootFinder
{
public:
BisectionRootFinder(){}
private:
virtual double doFindRoot( const Function1D& func, double min, double
max ) const;
};

The two flavors of findRoot are public fronts to doFindRoot, which does the real work. See also

http://www.gotw.ca/publications/mill18.htm
--
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
Alexander Grigoriev
2010-02-14 17:11:30 UTC
Permalink
THis is "name hiding" because of overload lookup rules.

You can deal with that by adding:

using RootFinder::findRoot;

in the derived class declaration.
Post by Dave
Hi folks,
Got the following class hierarchy, and am getting a strange compile
class RootFinder
{
virtual ~RootFinder(){}
double findRoot( const Function1D& func, double guess ) const;
virtual double findRoot( const Function1D& func, double min, double
max ) const = 0;
bool findGoodInterval( const Function1D& func, double guess, double&
min, double& max ) const;
};
class BisectionRootFinder : public RootFinder
{
BisectionRootFinder(){}
virtual double findRoot( const Function1D& func, double min, double
max ) const;
};
BisectionRootFinder rootFinder;
const double root = rootFinder.findRoot( func, guess );
error C2660: 'BisectionRootFinder::findRoot' : function does not
take 2 arguments
I'm not sure why this is happening, as it should be able to find the
non-virtual version of findRoot(...) that is in the base class. I can
BisectionRootFinder bisectRootFinder;
RootFinder& rootFinder = bisectRootFinder;
const double root = rootFinder.findRoot( func, guess );
and all works fine. But, why do I need to go through that extra step?
Am I declaring something wrong, or is VC just misbehaving? If it
matters, I am using Visual Studio 2008 Express (version 9.0.30729.1
SP)
Thanks.
Continue reading on narkive:
Loading...