When I run the following code:
#include <iostream>
class A
{
public:
virtual void foo()
{
std::cout << "Foo\n";
}
};
class B : A
{
public:
virtual void foo() override
{
A foo();
std::cout << "Bar\n";
}
};
int main()
{
B b;
b.foo();
}
I get the following result: Bar.
I understand that to get:
Foo
Bar
I would need to replace A foo(); with A::foo();.
But I'm having trouble understanding what A foo(); is, as it seems that that statement (or declaration?) is skipped.
Note: I'm using g++ 7.4 on a x86 machine.
Thanks!
A foo(); declares a function that has no arguments, returns an A and is called foo.
A::foo(); is something entirely different. It calls the method A::foo.
You are experiencing a phenomenon commonly referred to as most vexing parse. It usually manifests when trying to initialise a variable:
Type variable1;
Type variable2(value);
Type function1();
Type function2(Type);
It is easy to be misled into thinking that Type x(); and Type y(1); should roughly do a similar thing, but the former declares a function while the latter declares and defines a local variable.
In your case in the example, foo is not the member function A::foo but a local declaration of a function that would shadow the member function you are keen on calling.
The fact that this is seldom useful in function scopes is even more vexing, but that's just how the C++ parser works. Declaration syntax does not distinguish between global and local scope.
Related
The following code shows a function call another function.
Both have the same name, but different signatures.
This works as expected.
//declarations
void foo();
void foo(int);
int main(){
foo();
}
//definitions
void foo(){
foo(1);
}
void foo(int){}
The only difference I will make now, is wrap one of the functions into a structure:
//declarations
struct Bar{
void foo();
};
void foo(int);
int main(){
Bar bar;
bar.foo();
}
//definitions
void Bar::foo(){
foo(1);
}
void foo(int){}
This fails to compile.
In member function ‘void Bar::foo()’:
error: no matching function for call to ‘Bar::foo(int)’
foo(1);
^
note: candidate: void Bar::foo()
void Bar::foo(){
^
note: candidate expects 0 arguments, 1 provided
I don't understand why it wants to call foo(int) as a method, when the global function exists.
It doesn't mention anything about ambiguity, it just can't find the function.
Why is this happening, and how can I fix it?
side note: I'm wrapping old C code in a C++ wrapper, and most of the C++ methods are calls to the global C functions which pass in the wrapped struct implicitly. It's a similar situation to what is happening above (in terms of compiler errors).
The member function is hiding the global. It finds the name in the class context, therefore it not continue to search it in other contexts.
You need to call it like this:
::foo(1);
Another solution is to use forward declaration inside the function, like this:
void Bar::foo()
{
void foo(int);
foo(1);
}
As Praetorian suggests, here is another option:
void Bar::foo()
{
using ::foo;
foo(1);
}
I intended to call a private class member function, but by a copy&paste mistake pasted the line as this function is declared in the header file:
void DebugView::on_cbYAxisEnabled_stateChanged(int)
{
void updateAxisEnabled();
}
instead of
void DebugView::on_cbYAxisEnabled_stateChanged(int)
{
updateAxisEnabled();
}
Surprisingly, the code was compiled and executed. However the method updateAxisEnabled() was not executed.
So, why does it compile? Was here a local function declared within a method body or has void instructed the compiler to ignore whatever comes afterwards?
The compiler is Visual Studio 2008.
P.S.: I'm aware of class declaration/definition within functions, but not functions within functions in C++.
void updateAxisEnabled(); is a function declaration.
Sample:
#include <cstdio>
void a();
void b();
int main(void) {
a();
b();
return 0;
}
void a() {
void c(); // Declaration
c(); // Call it
}
void b() {
c(); // Error: not declared
}
void c() {
puts("Hello, world!");
}
It is perfectly allowed to declare a function inside a function scope: a function may be declared in any scope.
A common mistake among C++ programmers is indeed to:
void foo()
{
MyObject bar(); // 1
bar.someMethod(); // 2
}
this will miserably fail to compile because line 1 is not declaring a MyObject named bar and calling its constructor explicitly; rather, it is declaring a function named bar that returns a MyObject. Thefore, there is really no object to call someMethod on.
I would like to print two different things depending on whether a function is called statically with Foo::print() or from an instance of Foo foo; foo.print();
EDIT: Here is a class definition that definitely does not work, as answered by a few people already.
class Foo {
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
However, is there a good way of achieving this effect? Basically, I would like to do:
if(this is a static call)
do one thing
else
do another thing
Phrased in another way, I know PHP can check if the *this variable is defined or not to determine whether the function is called statically. Does C++ have the same capability?
No, it is directly prohibited by the standard:
ISO 14882:2003 C++ Standard 13.1/2 – Overloadable declarations
Certain function declarations cannot
be overloaded:
Function declarations that differ only in the return type cannot be overloaded.
Member function declarations with the same name and the same parameter types cannot be overloaded
if any of them is a static member function declaration (9.4).
...
[Example:
class X {
static void f();
void f(); // ill-formed
void f() const; // ill-formed
void f() const volatile; // ill-formed
void g();
void g() const; // OK: no static g
void g() const volatile; // OK: no static g
};
—end example]
...
Besides, it would be ambiguous anyway since it's possible to call static functions on instances:
ISO 14882:2003 C++ Standard 9.4/2 – Static members
A static member s of class X may be
referred to using the qualified-id
expression X::s; it is not necessary
to use the class member access syntax
(5.2.5) to refer to a static member. A
static member may be referred to using
the class member access syntax, in
which case the object-expression is
evaluated. [Example:
class process {
public:
static void reschedule();
}
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
—end example]
...
So there would be ambiguity with what you have:
class Foo
{
public:
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
int main()
{
Foo f;
// Call the static or non-static member function?
// C++ standard 9.4/2 says that static member
// functions are callable via this syntax. But
// since there's also a non-static function named
// "print()", it is ambiguous.
f.print();
}
To address your question about whether you can check what instance a member function is being called on, there is the this keyword. The this keyword points to the object for which function was invoked. However, the this keyword will always point to an object i.e. it will never be NULL. Therefore it's not possible to check if a function is being called statically or not à la PHP.
ISO 14882:2003 C++ Standard 9.3.2/1 – The this pointer
In the body of a nonstatic (9.3)
member function, the keyword this is a
non-lvalue expression whose value is
the address of the object for which
the function is called.
It is definitely not allowed. I don't see any clean way of achieving this. What is exactly the problem that you want to solve this way?
You can't do that exactly, see In silico's answer.
But you can make Foo::print() and Foo foo; print(foo); do different things. (Define void print(Foo& foo) in the same namespace as class Foo, it will be found by ADL).
In any case, this is not a good idea. You have two functions very similar in name which do completely different things, which violates good design principles.
The answer is no, because you can't overload based on a return type.
You can certainly have static methods in a class, but you can't have:
static void foo();
void foo();
Because they have the same method signature.
EDIT: I saw your comment saying why you wanted to do this, and that you wanted to access member variables. You'd need to do this:
static void print(Foo f);
void print();
....
static void Foo::print(Foo f)
{
int a = f.a;
// do something with a
}
(Or create getters and setters in Foo, etc, but that's the general idea)
1) In case of different return type of functions overloading is not possible in method overloading.
2) also if we pass same parameters in the functions define under the same class then it can not be overload.
void foo()
{
bar(); // error: ‘bar’ has not been declared
}
void bar()
{
}
namespace N
{
void foo()
{
N::bar(); // error: ‘bar’ is not a member of ‘N’
}
void bar()
{
}
}
class C
{
static void foo()
{
C::bar(); // works just fine
}
static void bar()
{
}
};
What is the rationale behind this inconsistency of treating calls to functions above their declaration? How come I can do it inside a class, but not inside a namespace or at global scope?
You can define member functions either inside the class, or after the class declaration, or some of each.
To get some consistency here, the rules for a class with functions defined inline is that it still has to be compiled as if the functions were defined after the class.
Your code
class C {
static void foo()
{
C::bar(); // works just fine
}
static void bar()
{ }
};
compiles the same as
class C {
static void foo();
static void bar();
};
void C::foo()
{ C::bar(); }
void C::bar()
{ }
and now there is no magic in the visibility, because the functions can all see everything declared in the class.
Namespaces can be reopened and new things can be added in any place.
Classes cannot be reopened - all their contents must be put in
single place.
Function prototypes are legal in namespaces but not in classes.
You can write
namespace n
{
void foo();
void bar()
{
foo();
}
void foo()
{
}
}
But not
class C
{
void foo();
void bar()
{
foo();
}
void foo()
{
}
}
So classes need such feature much more and it is much easier to implement it for them than for namespaces.
Well maybe because you have your class declaration in one place, and the compiler can easily obtain the information of it's members.
A namespace, on the other hand, can have it's stuff in tons of different files, and you can't expect the compiler to look through them, because it doesn't know where to look in the first place.
To avoid this, just use function prototypes.
I'm not sure but my thought is that a class is somewhat an object (badly used) where all its internal components work together (generally speaking), its member will definitely need its methods.
But a namespace is different, functions are not related. It means that a function isnt intended to work with every other functions inside the namespace.
So splitting declaration and definitions is the best thing you could do.
If foo() needs bar() its most likely going to be in the same declaration file, and would work that way
See the quote below from the Standard
3.3.7 Class scope [basic.scope.class]
1) The following rules describe the scope of names declared in classes. 1) The potential
scope of a name declared in a class consists not only of the
declarative region following the name’s point of declaration, but also
of all function bodies, default arguments, and
brace-or-equalinitializers of non-static data members in that class
(including such things in nested classes).
2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in
the completed scope of S. No diagnostic is required for a violation of this rule.
typedef int c;
enum { i = 1 };
class X {
char v[i]; // error: i refers to ::i
// but when reevaluated is X::i
int f() { return sizeof(c); } // OK: X::c
char c;
enum { i = 2 };
};
I would like to print two different things depending on whether a function is called statically with Foo::print() or from an instance of Foo foo; foo.print();
EDIT: Here is a class definition that definitely does not work, as answered by a few people already.
class Foo {
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
However, is there a good way of achieving this effect? Basically, I would like to do:
if(this is a static call)
do one thing
else
do another thing
Phrased in another way, I know PHP can check if the *this variable is defined or not to determine whether the function is called statically. Does C++ have the same capability?
No, it is directly prohibited by the standard:
ISO 14882:2003 C++ Standard 13.1/2 – Overloadable declarations
Certain function declarations cannot
be overloaded:
Function declarations that differ only in the return type cannot be overloaded.
Member function declarations with the same name and the same parameter types cannot be overloaded
if any of them is a static member function declaration (9.4).
...
[Example:
class X {
static void f();
void f(); // ill-formed
void f() const; // ill-formed
void f() const volatile; // ill-formed
void g();
void g() const; // OK: no static g
void g() const volatile; // OK: no static g
};
—end example]
...
Besides, it would be ambiguous anyway since it's possible to call static functions on instances:
ISO 14882:2003 C++ Standard 9.4/2 – Static members
A static member s of class X may be
referred to using the qualified-id
expression X::s; it is not necessary
to use the class member access syntax
(5.2.5) to refer to a static member. A
static member may be referred to using
the class member access syntax, in
which case the object-expression is
evaluated. [Example:
class process {
public:
static void reschedule();
}
process& g();
void f()
{
process::reschedule(); // OK: no object necessary
g().reschedule(); // g() is called
}
—end example]
...
So there would be ambiguity with what you have:
class Foo
{
public:
string bla;
Foo() { bla = "nonstatic"; }
void print() { cout << bla << endl; }
static void print() { cout << "static" << endl; }
};
int main()
{
Foo f;
// Call the static or non-static member function?
// C++ standard 9.4/2 says that static member
// functions are callable via this syntax. But
// since there's also a non-static function named
// "print()", it is ambiguous.
f.print();
}
To address your question about whether you can check what instance a member function is being called on, there is the this keyword. The this keyword points to the object for which function was invoked. However, the this keyword will always point to an object i.e. it will never be NULL. Therefore it's not possible to check if a function is being called statically or not à la PHP.
ISO 14882:2003 C++ Standard 9.3.2/1 – The this pointer
In the body of a nonstatic (9.3)
member function, the keyword this is a
non-lvalue expression whose value is
the address of the object for which
the function is called.
It is definitely not allowed. I don't see any clean way of achieving this. What is exactly the problem that you want to solve this way?
You can't do that exactly, see In silico's answer.
But you can make Foo::print() and Foo foo; print(foo); do different things. (Define void print(Foo& foo) in the same namespace as class Foo, it will be found by ADL).
In any case, this is not a good idea. You have two functions very similar in name which do completely different things, which violates good design principles.
The answer is no, because you can't overload based on a return type.
You can certainly have static methods in a class, but you can't have:
static void foo();
void foo();
Because they have the same method signature.
EDIT: I saw your comment saying why you wanted to do this, and that you wanted to access member variables. You'd need to do this:
static void print(Foo f);
void print();
....
static void Foo::print(Foo f)
{
int a = f.a;
// do something with a
}
(Or create getters and setters in Foo, etc, but that's the general idea)
1) In case of different return type of functions overloading is not possible in method overloading.
2) also if we pass same parameters in the functions define under the same class then it can not be overload.