Problem with function not being visible

C

chris

Guys, I have the following piece of code. Could you please help me understand why
b.ToString( ) cannot be called while b.foo( ) can? When I compile I get (gcc, but
visual studio gives the same pretty much). Thanks

$ g++ -Wall foo.cpp
foo.cpp: In function `int main(int, char**)':
foo.cpp:21: error: no matching function for call to `Bar::ToString()'
foo.cpp:14: note: candidates are: virtual std::string Bar::ToString(std::string&) const

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {
public:
virtual std::string ToString (std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
};

class Bar: public Foo<int> {
public:
std::string ToString (std::string& pfx) const { return (std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}
 
V

Victor Bazarov

Guys, I have the following piece of code. Could you please help me
understand why b.ToString( ) cannot be called while b.foo( ) can?
When I compile I get (gcc, but visual studio gives the same pretty
much). Thanks

Binding a reference to non-const to a temporary is prohibited.
$ g++ -Wall foo.cpp
foo.cpp: In function `int main(int, char**)':
foo.cpp:21: error: no matching function for call to `Bar::ToString()'
foo.cpp:14: note: candidates are: virtual std::string
Bar::ToString(std::string&) const

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {

You should avoid using names that begin with an underscore and
a capital letter. They are reserved by the implementation.
public:
virtual std::string ToString (std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }

Are you trying to call the virtual function (declared just before) here?
You cannot bind the temporary to a refernece to non-const. You have to
change the body to be

{ std::string s; return ToString(s); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
};

class Bar: public Foo<int> {
public:
std::string ToString (std::string& pfx) const
{ return (std::string("test")); }
void* _foo ( ) const { return(NULL); }

I've reformatted it a bit, just to fit them on a line.
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

V
 
F

Fei Liu

Guys, I have the following piece of code. Could you please help me understand why
b.ToString( ) cannot be called while b.foo( ) can? When I compile I get (gcc, but
visual studio gives the same pretty much). Thanks

$ g++ -Wall foo.cpp
foo.cpp: In function `int main(int, char**)':
foo.cpp:21: error: no matching function for call to `Bar::ToString()'
foo.cpp:14: note: candidates are: virtual std::string Bar::ToString(std::string&) const

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {
public:
virtual std::string ToString (std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
};

class Bar: public Foo<int> {
public:
std::string ToString (std::string& pfx) const { return (std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

Gratz, you have manged to demonstrate two C++ gotchas in your short
code: binding temporaries to non-const reference and name hiding. When
derived class uses same name declared in base class, the name in base
class is hidden. The example below is how you fix them:

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {
public:
virtual std::string ToString (const std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
virtual ~Foo(){}
};

class Bar: public Foo<int> {
public:
using Foo<int>::ToString;
std::string ToString (const std::string& pfx) const { return
(std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}
 
A

Andre Kostur

(e-mail address removed) wrote in

Guys, I have the following piece of code. Could you please help me
understand why b.ToString( ) cannot be called while b.foo( ) can? When
I compile I get (gcc, but visual studio gives the same pretty much).
Thanks

$ g++ -Wall foo.cpp
foo.cpp: In function `int main(int, char**)':
foo.cpp:21: error: no matching function for call to `Bar::ToString()'
foo.cpp:14: note: candidates are: virtual std::string
Bar::ToString(std::string&) const

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {
public:
virtual std::string ToString (std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
};

class Bar: public Foo<int> {
public:
std::string ToString (std::string& pfx) const { return
(std::string("test")); } void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

ToString no longer exists taking no parameters when called on a Bar. As
soon as you declared std::string ToString(std::string& pfx) in your derived
class, it will hide all other declarations of ToString. If you still want
to use the no-parameter form of ToString, you'll have to add a using Foo
<int>::ToString into your Bar class.

In addition to Victor's comment that you may not bind a temporary to a non-
const reference. But that's a different issue.
 
F

Fei Liu

Fei said:
Gratz, you have manged to demonstrate two C++ gotchas in your short
code: binding temporaries to non-const reference and name hiding. When
derived class uses same name declared in base class, the name in base
class is hidden. The example below is how you fix them:

#include <stdlib.h>
#include <string>
using namespace std;

template <typename _T> class Foo {
public:
virtual std::string ToString (const std::string& pfx) const = 0;
std::string ToString ( ) const { return(ToString(std::string( ))); }
virtual void* _foo ( ) const = 0;
void* foo( ) const { return (_foo( )); }
virtual ~Foo(){}
};

class Bar: public Foo<int> {
public:
using Foo<int>::ToString;
std::string ToString (const std::string& pfx) const { return
(std::string("test")); }
void* _foo ( ) const { return(NULL); }
};

int main (int argc, char **argv) {
Bar b;
b.foo( );
b.ToString( );
return (0);
}

Actually there are 3 errors in your code, notice I also added
virtual ~Foo(){}. Although arguably it's not an issue in your short
example, but make it a habit to declare a virtual destructor in the base
virtual class. It'll save you a lot of headache in the future.

Fei
 
C

chris

ToString no longer exists taking no parameters when called on a Bar. As
soon as you declared std::string ToString(std::string& pfx) in your derived
class, it will hide all other declarations of ToString. If you still want
to use the no-parameter form of ToString, you'll have to add a using Foo
<int>::ToString into your Bar class.

Thanks a lot - that is the case indeed!
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,298
Messages
2,571,539
Members
48,274
Latest member
HowardKipp

Latest Threads

Top