C++ Overload Static Function with Non-Static Function - c++

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.

Related

Is it possible to declare a pure virtual function with deduced return type? If not, why not? [duplicate]

This question already has answers here:
Why can't virtual functions use return type deduction?
(3 answers)
Closed 7 years ago.
I have some abstract class, and I wonder whether I could declare a function with this signature inside it:
virtual auto some_function() = 0;
In case it helps answering, I'm trying to implement a class that will allow to register callbacks for different types, so that when a member template function is called, it will look for its argument's typeid in an associative container and call its associated callback on it.
JUSTIFICATION FOR THE ORIGINALITY OF THE QUESTION
According to N3638 - Return type deduction for normal functions
It would be possible to allow return type deduction for virtual
functions (...)
so while auto virtual is not allowed in C++, it is a possible alternative design according to Jason Merrill.
So this question: Is it possible to declare a pure virtual function with deduced return type? If not, why not? (I have fixed the title to match the real question and its intent) is not the same as the answer to the question Is it possible to declare a virtual function with deduced return type?
Maybe it would help if moderators considered the question and not just its title.
The question does not make sense. auto means deduced from initialization:
auto i = 1; // int
or deduced from return statement:
auto f() { return 2; } // int
A pure virtual function by definition does not have a definition of a virtual function (*), so it does not have a return statement, so the return type could not be deduced from anything.
You must have an incorrect understanding of C++ to think this could work.
Short answer: C++ is statically typed.
ADDITIONAL DETAIL
Note (*): A pure virtual function can have definition, but it is the
definition of a non-virtual function callable with the scope
resolution operator:
struct Base {
virtual void f() = 0;
};
void Base::f() {
std::cout << "Base::f()\n";
}
struct Der : Base {
virtual void f();
};
void Der::f() {
cout << "Der::f()\n";
}
int main() {
Der d;
d.Base::f();
}
Test here; outputs:
Base::f()
OTOH, Base::f() can't be called via the virtual call mechanism:
struct Base {
Base ();
virtual void f() = 0;
};
void call (Base *p) {
cout << "Base::Base()\n";
p->f();
}
Base::Base () {
call(this);
}
Test here; generates:
Runtime error
The pure virtual function can't be called virtually.
A pure virtual function return type could be deduced from the return statement of the non-virtual definition (**), but it would create another special case and it wouldn't solve the present problem (the return statement is not known in the base class).
(**) A virtual function can't be declared auto in C++, but there is not strong reason to disallow auto virtual function.
REPLY TO COMMENT
The return type could be hypothetically deduced from a derived class'
implementation.
OK, let's say we do that:
struct Base {
virtual auto f() = 0;
};
struct Der1 : Base {
virtual int f();
};
Then the return type of Base::f() is int, right? This is assuming that Der can be found in the compiler, even if it is latter defined, elsewhere, and the program is compiled separately (or maybe you suggest this feature wouldn't be compatible with separate compilation?). Now the class can be derived elsewhere:
struct Der2 : Base {
virtual std::string f();
};
So what is the type of return type of Base::f()? int, string, neither, both, a cat?
In C++ an expression must have a well defined type: a declared type, aka compile time type, aka static type. These words are equivalent.
For example, a pointer variable declare type never changes, not does the declared type of *p, but the real aka runtime aka dynamic type of *p depends on the value of p:
Base *p = 0;
// declared type of p is Base*, real type of *p is Base,
// declared type of *p is Base, real type of *p is undefined
cout << "typeid (p): " << typeid (p).name() << "\n";
p = new Der1;
// declared type of p is Base*, real type of *p is Base,
// declared type of *p is Base, real type of *p is Der1
cout << "typeid (p): " << typeid (p).name() << "\n";
cout << "typeid (*p): " << typeid (*p).name() << "\n";
The declared type is used by the compiler:
for name lookup
for overload resolution (overloaded non member functions, overloaded member functions, overloaded operators)
for member access checking (public, protected, private)
The real type controls the runtime virtual call behavior.
The distinction of declared vs. real type is one of the most important C++ concepts!

These two member functions, why don't they overload? [duplicate]

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.

Why must a method be declared in a C++ class definition?

If only define this method it will have a compiler error.
void classA::testMethod() {
}
And so it must be declared first:
class classA {
void testMethod();
};
Why should these be declared?
I know for common C method methods it is not needed declare, but they can just be defined:
void test() {
}
There are several secondary reasons both objective and subjective (i.e. allows to specify visibility, serves as an interface for the class and probably several others related to compiling and linking phases and TU symbols visibility, not to mention a class is the basic encapsulation unit, with all that implies) but an unquestionable one is that the standard dictates it:
N3797 - class.mfct/p2
A member function may be defined (8.4) in its class definition, in
which case it is an inline member function (7.1.2), or it may be
defined outside of its class definition if it has already been
declared but not defined in its class definition. A member function
definition that appears outside of the class definition shall appear
in a namespace scope enclosing the class definition. Except for member
function definitions that appear outside of a class definition, and
except for explicit specializations of member functions of class
templates and member function templates (14.7) appearing outside of
the class definition, a member function shall not be redeclared.
emphasis mine.
You don't need to declare the method before you define it, but you need to declare class methods in the class. Else it wouldn't be a class method.
That may seem like a contradiction, but a definition is also a declaration. So what this means is that the definition may appear in the class itself:
class A {
void testMethod() { /*...*/ }
};
[edit]
Also, practically speaking, inside the class declaration there are private, protected and public parts. This is needed to for encapsulation. If you could declare methods outside the class, you would lose encapsulation. Anybody could access private members merely by defining extra getters and setters, even when those would not make sense. Class invariants would become meaningless.
It helps encapsulation. If you have a class A
class A {
public:
foo();
bar();
}
You can be sure that only methods foo and bar mess with the private data members of the class. (Or pointer magic or undefined behavior of course)
All of the previous answers are correct as far as they go, but
they fail to point out the reason behind the rule. In C++,
a class definition is closed; you cannot add to it later. This
is necessary for non-static data members, since they determine
the size (and the implicitly generated special functions), but
it is a basic principle in C++ for all class members: not just
data, but functions, types, etc. It is considered essential for
good encapsulation.
This is true for most (but not all) languages which support the
concept of class.
This also explains why it the situation is different for
namespaces (which aren't closed).
Note the use of the qualifier ::. It means
on the left you have a namespace or class identifier
on the right you have a namespace, class, or method / function identifier
So writing void A::testMethod() assumes that there is a class or namespace A defined - this is how C++ is defined. And this applies to
void A::testMethod();
as well as to
void A::testMethod()
{
}
Also note the global namespace where you have indeed nothing at the left of :: as in
void ::testMethod()
{
}
And by definition the global namespace is always defined so the above code defines a function similar to C-style without the qualifier.
Even if it were not mandated by the standard, there are the following two reasons why you need to declare all class methods in the class definition.
You can only declare something as public, private or protected in the class declaration, you can't do so at the method definition in the .cpp file. So what visibility would your free-standing class method have?
If the standard decided to select one of the three as the default (C++ defaults to private), and place that visibility on your method, you now have a scoping problem. Even the most restrictive visibility (private) means that you can use the method in any other member method, including those defined before it in the source file. Without the declaration in the class definition, those earlier functions would not be aware of your free standing method, thus you violate the scoping rules.
In your foo.h header:
class foo
{
public:
foo() {}
virtual ~foo() {}
declaredMethod();
};
In your foo.cpp
foo::declaredMethod()
{
...
freeStandingMethod(); // This should be legal, but it can't work since we
// haven't seen foo::freeStandingMethod() yet
...
}
foo::freeStandingMethod()
{
...
}
Even if you could make this work in the same .cpp file, it's legal to place foo::freeStandingMethod() in a different .cpp file from foo::declaredMethod() at which point this becomes impossible.
This is not an answer, but you might find it informative and fun.
Adding 2 template functions to your class will effectively allow you to call any free function that takes an object of that class as the first parameter:
#include <string>
#include <iostream>
struct puppy {
puppy(std::string name)
: _name(std::move(name))
{}
const std::string& name() const noexcept {
return _name;
}
void set_name(std::string name) {
_name = std::move(name);
}
template<class F, class ...Args>
auto perform(F&& f, Args&&...args) const
-> decltype(f(*this, std::forward<Args>(args)...))
{
return f(*this, std::forward<Args>(args)...);
}
template<class F, class ...Args>
auto perform(F&& f, Args&&...args)
-> decltype(f(*this, std::forward<Args>(args)...))
{
return f(*this, std::forward<Args>(args)...);
}
private:
std::string _name;
};
void woof(const puppy& p) {
std::cout << "puppy " << p.name() << " woofs!" << std::endl;
}
void indented_woof(const puppy&p, size_t indent) {
std::cout << std::string(indent, ' ');
woof(p);
}
void complex_woof(const puppy& p, int woofs)
{
std::cout << "attention!" << std::endl;
for (int i = 0 ; i < woofs ; ++i) {
p.perform(indented_woof, 4);
}
}
std::string name_change(puppy& p, std::string(new_name))
{
auto old_name = p.name();
p.set_name(std::move(new_name));
return old_name;
}
int main()
{
puppy fido { "fido" };
fido.perform(woof);
fido.perform(complex_woof, 10);
auto old_name = fido.perform(name_change, "bonzo");
fido.perform(woof);
std::cout << "changed name from " << old_name << std::endl;
return 0;
}
"Methods" or "member functions" (as is the more common terminology in C++) are part of the class declaration. Since you must declare a C++ class in one single place, you must make sure that all "member functions" (or "methods") are already present in that declaration.
I know for common C method methods it is not needed declare, but they
can just be defined
When you refer a "common C method" in C++, you actually mean a "common function". Note that you can declare classes anywhere you can declare such functions.
Also, note that you can declare a member function with a body. You do not have to separate declaration and definition. I.e. this is perfectly valid:
class A{
void privateMethod() {
// do something here...
}
public:
void publicMethod() {
// do something here...
}
};
why should declare these? I know for common c method, there is no need to declare, instead of it just define it:
There is no method in C, just attribute of an struct, wich can be function Pointeur, then associated to a function addresse.
Furthermore you have to declare it in the class definition for the same reason you do it in C:
The compilateur will transform this pre-declaration into a function pointeur then associate to the said methode int the construction of your object.
If a definition of a C++ class should be transformed to a C struct the code would be like this:
struct Aclass {
void (*Amethode))(int);
}
void Amethode(int) { return (0); }
Aclass primaryObject = {&Amethode};
Aclass* AclassConstructor() {
Aclass* object;
object = malloc(sizeof(Aclass));
memcpy(object, primaryObject, sizeof(Aclass));
return (object);
}

Using (::) in a class's member function definition

I was testing out classes and I made this class
class Point
{
private:
int x,y;
public:
void setit(int new_x,int new_y);
void set_x(int new_x);
void set_y(int new_y);
int get_x();
int get_y();
};
now I went ahead and wrote the function definitions for all the public functions but,
There is something that puzzled me when i was writing the void set(int new_x,int new_y);
function definition
void Point::setit(int new_x, int new_y){
Point::set_x(new_x);
Point::set_y(new_y);
}
void Point::setit(int new_x, int new_y){
set_x(new_x);
set_y(new_y);
}
I noticed that the two previous function definitions have the exact same effect.
I thought that without the :: operator it wouldn't work because it would search for the functions outside the class, since I no longer signify they are in the Point class
Can anyone explain why they both have the same effect??
Thank You.
:: is the scope resolution operator; it can tell the compiler exactly where to look for a name.
The Point::set_x is simply an extended syntax for calling a member function.
set_x(new_x);
Is short for
this->set_x(new_x);
And
Point::set_x(new_x);
Is equivalent for
this->Point::set_x(new_x);
It allows you to select which function to call when a class hides a function in a parent class. For instance:
struct A {
void f();
};
struct B : public A {
void f(); // Hides A::f
};
B binst;
binst.f(); // Calls B::f
binst.A::f(); // Calls A::f
One thing you can do with this syntax is call the member function of a parent class from the overridden virtual function of a base class, allowing you to use the "default implementation" provided by the base class. You can also do it from outside the class, similar to hidden functions:
struct A {
virtual void f() {
cout << "A::f" << endl;
}
};
struct B : public A {
virtual void f() override {
cout << "B::f" << endl;
A::f(); // if we just did f(), it would call B::f, and we
// would get infinite recursion
}
};
B b;
b.f(); // prints B::f A::f
b.A::f(); // prints B::f
Inside a class member function, all the class member names are in scope, so set_x is found.
Moreover, the class name itself is visible inside class member functions (it is said to be injected), and thus Point::set_x is also found. But for the same reason, Point::Point::set_x and Point::Point::Point::Point::set_x are also ways to name the function.
:: is a scope resolution operator. To access the function in the scope of the Point class' namespace you can use the :: operator, but because the function setit(int new_x, int new_y) is already in the same scope as set_x and set_y, there is no requirement to define the overall scope of those functions. The program will call the functions with matching symbols to set_x and set_y in the most local scope.

What does the :: mean in C++? [duplicate]

This question already has answers here:
When do I use a dot, arrow, or double colon to refer to members of a class in C++?
(4 answers)
Closed 6 years ago.
void weight_data::rev_seq(string &seq){
//TODO
std::reverse(seq.begin(), seq.end());
}
In this C++ method, I think this method does not return anything, so the prefix is void, what does :: tell the relationships between weight_data and rev_seq(string &seq)? Thanks!
void is the return type. :: is the scope resolution operator, so it means rev_seq is inside the scope of weight_data. weight_data could be either a namespace or a class (based on what you've given, it's not possible to say which).
In C++,
A::B means B is an identifier within either namespace or class type A,
A.B means B is a member of the struct, class, or union type an instance of which is referred to by the object or reference A, and
A->B means B is a member of the struct, class, or union type an instance of which is referred to by the pointer A. (It's equivalent to (*A).B.)
In some other languages, all three cases are covered by a . only.
Note that in C++, member function don't have to be implemented (defined) within their class' definition. (If they are, they are implicitly inline.) They can be, and often are, implemented in separate implementation (.cpp) files. This has the advantage that not all users of a class need to recompile when you change an implementation of one of the class' member functions. So unless weight_data is a namespace name, void weight_data::rev_seq(string &seq) {...} is such a definition of a class member outside of its class.
weight_data is a namespace or class name.
The line void weight_data::rev_seq(string &seq) tells the compiler that this is the definition of the rev_seq(string &seq) member function from the weight_data. If this just said void rev_seq(string &seq) { ... } the compiler would think that a non-member function was being defined, as opposed to the rev_seq(string &seq) member function of the weight_data class.
class weight_data
{
void rev_str(string &seq);
}
It can also mean that rev_str refers to a function that is part of namespace weight_data.
namespace weight_data
{
void rev_str(string &seq);
}
Just thought of adding 2 more interesting things about the ::
a) Operator :: is both a unary and a binary operator
struct A{
int m;
};
int x;
int main(){
::x; // Unary
int (A::*p) = &A::m; // Binary
}
b) $10.3/12 - "Explicit qualification with the scope operator (5.1) suppresses the virtual call mechanism."
struct A{
virtual void f(){cout << 1;}
};
struct B : A{
void f(){cout << 2;}
};
int x;
int main(){
B b;
A &ra = b;
ra.f(); // dynamic binding, prints 2
ra.A::f(); // suppress VF mechanism, prints 1.
}