Two functions declarations share one definition, is this legal? - c++

Another newbie question:
int foo(); // outer foo function
int main() {
int foo(); // inner foo function
cout << foo() << endl;
}
int foo() { // one definition
return 42;
}
From my understanding, an inner declaration of either function or object will hide outer one, if any.
So the above outer foo() and inner foo() should be two distinct functions.
But they are sharing one definition, which seems confusing.
Is it legal that two distinct functions share one definition? How about two distinct object variables?
(This is C++ question but the syntax seems also fits C.)
Edit:
It is verified that outer and inner foo are the same funciton using pointer to function:
pf_outer = 0x400792
pf_inner = 0x400792

The inner foo is just another forward deceleration of the same foo(). Consider the following example:
int foo();
int foo();
int main() {
cout << foo() << endl;
}
int foo() { // one definition
return 42;
}
This will compile and run and there is no ambiguity because the compiler will replace the use of the same function with the same code.
It is fine to re declare functions.

This is perfectly fine to redeclare a function like this, we can see this from draft C++ standard in two places, in section 3.1 Declarations and definitions which says:
A declaration (Clause 7) may introduce one or more names into a
translation unit or redeclare names introduced by previous
declarations.[...]
and goes on to say:
A declaration is a definition unless it declares a function without
specifying the function’s body [...]
and in section 13.1 Overloadable declarations paragraph 3 which says:
Parameter declarations that differ only in the use of equivalent
typedef “types” are equivalent. A typedef is not a separate type, but
only a synonym for another type (7.1.3). [ Example:
typedef int Int;
void f(int i);
void f(Int i); // OK: redeclaration of f(int)
void f(int i) { /* ... */ }
void f(Int i) { /* ... */ } // error: redefinition of f(int)
—end example ]
Both declarations will refer to the same definition, you are not allowed to redefine the function.
The function declarations of are also allowed to differ by their outermost cv-qualifiers as well.

Related

Declaration of function prototypes within classes in C++? [duplicate]

I have been programming in C++ for quite some time and I never thought about this until today.
Consider the following code:
struct foo
{
// compiles fine
void bar()
{
a = 1;
my_int_type b;
b = 5;
}
// Just a declaration, this fails to compile, which leads me to assume that
// even though the bar() method is declared and defined all at once, the
// compiler looks/checks-syntax-of the class interface first, and then compiles
// the respective definitions...?
void bar2(my_int_type); // COMPILE ERROR
my_int_type b; // COMPILE ERROR because it comes before the typedef declaration
typedef int my_int_type;
my_int_type a;
void bar3(my_int_type); // compiles fine
};
int main()
{
foo a;
a.bar();
return 0;
}
Is my understanding of why the errors occur (see bar2() comment above) correct/incorrect? Either way, I would appreciate an answer with a simplistic overview of how a single-pass C++ compiler would compile the code given above.
For the most part, a C++ file is parsed top-to-bottom, so entities must be declared before they are used.
In your class, bar2 and b are invalid because they both make use of my_int_type, which has not yet been declared.
One exception to the "top-to-bottom" parsing rule is member functions that are defined inside the definition of their class. When such a member function definition is parsed, it is parsed as if it appeared after the definition of the class. This is why your usage of my_int_type in bar is valid.
Effectively, this:
struct foo
{
void bar()
{
my_int_type b;
}
typedef int my_int_type;
};
is the same as:
struct foo
{
void bar();
typedef int my_int_type;
};
inline void foo::bar()
{
my_int_type b;
}
Compiler just starts to go down in a block. Any symbol which is not familiar to it will be considered as a new symbol which is not defined. This is the scheme behind the function definition or header files.
You can suppose that the compiler first makes a list of definitions so the bar() method should get compiled correctly because the definitions have provided before.
It has a lot to do with visibility. I think your confusion may come from assuming a single pass. Think of class parsing as done in two stages.
Parse class definition.
Parse method implementation.
The advantage to this is we have visibility of the entire class from within class member functions.

Why doesn't the order of methods in a class matter in C++?

I have been programming in C++ for quite some time and I never thought about this until today.
Consider the following code:
struct foo
{
// compiles fine
void bar()
{
a = 1;
my_int_type b;
b = 5;
}
// Just a declaration, this fails to compile, which leads me to assume that
// even though the bar() method is declared and defined all at once, the
// compiler looks/checks-syntax-of the class interface first, and then compiles
// the respective definitions...?
void bar2(my_int_type); // COMPILE ERROR
my_int_type b; // COMPILE ERROR because it comes before the typedef declaration
typedef int my_int_type;
my_int_type a;
void bar3(my_int_type); // compiles fine
};
int main()
{
foo a;
a.bar();
return 0;
}
Is my understanding of why the errors occur (see bar2() comment above) correct/incorrect? Either way, I would appreciate an answer with a simplistic overview of how a single-pass C++ compiler would compile the code given above.
For the most part, a C++ file is parsed top-to-bottom, so entities must be declared before they are used.
In your class, bar2 and b are invalid because they both make use of my_int_type, which has not yet been declared.
One exception to the "top-to-bottom" parsing rule is member functions that are defined inside the definition of their class. When such a member function definition is parsed, it is parsed as if it appeared after the definition of the class. This is why your usage of my_int_type in bar is valid.
Effectively, this:
struct foo
{
void bar()
{
my_int_type b;
}
typedef int my_int_type;
};
is the same as:
struct foo
{
void bar();
typedef int my_int_type;
};
inline void foo::bar()
{
my_int_type b;
}
Compiler just starts to go down in a block. Any symbol which is not familiar to it will be considered as a new symbol which is not defined. This is the scheme behind the function definition or header files.
You can suppose that the compiler first makes a list of definitions so the bar() method should get compiled correctly because the definitions have provided before.
It has a lot to do with visibility. I think your confusion may come from assuming a single pass. Think of class parsing as done in two stages.
Parse class definition.
Parse method implementation.
The advantage to this is we have visibility of the entire class from within class member functions.

Non member function can be declared multiple times while member function can only be declared once?

Non mumber function can be delcared multiple times while member function can only be declared once? Is this right ? My example seems saying yes.
But Why ?
class Base{
public:
int foo(int i);
//int foo(int i=10); //error C2535: 'void Base::foo(int)' : member function already defined or declared
};
//but it seems ok to declare it multiple times
int foo(int i);
int foo(int i=10);
int foo(int i)
{
return i;
}
int main (void)
{
int i = foo();//i is 10
}
From the Standard (2003), §8.3.6/4 says,
For non-template functions, default
arguments can be added in later
declarations of a function in the same
scope.
Example from the Standard itself:
void f(int, int);
void f(int, int = 7);
The second declaration adds default value!
Also see §8.3.6/6.
And an interesting (and somewhat related) topic:
Default argument in the middle of parameter list?
And §9.3/2,
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.
Hope that helps.
You get the same result with this simplified version:
int foo() ;
int foo() ; // OK -- extern functions may be declared more than once
class C {
int foo() ;
int foo() ; // Error -- member function may not be declared more than once
} ;
Perhaps the reason is historical -- lots of C code used redeclaration of extern functions, so they had to be allowed.
It certainity works - but I think it is bad practice.

c++ order of defs in the class, surprise

Stroustrup states in C++ Language book that order of definitions in the class does not matter.
Indeed:
class C1 {
int foo() { return bar(); } // where is bar() ?
int bar() { return m_count; } // oh, here is bar(). but where is m_count ?
int m_count; // here is m_count. Better late than never !
}
This compiles. Despite misordering. As promised.
So far, so good.
However, this does not compile:
class C2 {
void baz(Inner *p) {} // we were promised that order does not matter
// is Inner defined ?
struct Inner {}; // yes, Inner is define here.
};
This looks a contradiction to Stroustrup's promise of free ordering inside the class. Quoting Stroustrup: "A member function declared within a class can refer to every member of the class as if the class were completely defined before the member function bodies were considered".
Does anybody know a ref to standard clause that allows C1 and disallows C2 ? I am curious why C2 was disallowed while C1 is allowed. Is it compiler bug that contradicts the standard, maybe ?
Note that the following compiles fine (in VS2008):
class C2 {
void baz() { Inner* i = new Inner(); }
struct Inner {};
};
There are two differences between your two examples. The first uses an undeclared symbol inside the body of a function and the second uses an undeclared type in the signature of the function.
I suspect that my example and your first example both work because the function bodies aren't resolved until after the entire class declaration has been parsed. The function signatures have to make sense as soon as they are encountered.
An identifier that denotes a type must be declared prior to use. This has to do with the complicated structure of C++ grammar. The compiler simply cannot parse certain code if it does not know beforehand which identifiers are types.
You are confusing "declarations" with "definitions". The inner class must be declared - if only forward declared - before it can be used.
The order of definition does not matter, but the order of declaration does.
In C++, a declaration means (roughly) stating the "kind" or type of a symbol:
class A; --> A is of kind "class"
void foo(int); --> foo is a function that takes an int and returns nothing
A definition, however, fully defines what the symbol relates to. As in C, a definition happens to be a declaration too.
Finally, to muddy the waters further, for user-declared types, sometimes a definition is required (complete-type) while sometimes a simple declaration is sufficient...
Now, let us revise your issue, I'll illustrate it with a simple example using C++0x:
struct A {
void foo() { ++count; }
void bar(decltype(count) c); // error: 'count' was not declared in this scope
int count;
};
struct B {
void foo() { Inner a; a.foo(); }
void bar(Inner& i); // error: 'Inner' has not been declared
struct Inner { void foo(); };
};
As you can notice, A::foo is parsed correctly, while A::bar is not.
The issue comes from the fact that the compiler "cheats": the methods body are fully analyzed only once the class has been completely parsed. Therefore it is fine to refer to a yet undeclared type/attribute/function in a function body, but it is not fine to refer to it in a function signature (declaration).
You could say that to the compiler, the code is equivalent to:
struct A {
void foo();
void bar(decltype(count) c); // error: 'count' was not declared in this scope
int count;
};
void A::foo() { ++count; }
struct B {
void foo();
void bar(Inner& i); // error: 'Inner' has not been declared
struct Inner { void foo(); };
};
void B::foo() { Inner a; a.foo(); }
Stroustrup sentence is "easy", but not necessarily accurate. For example, using Inner as an attribute requires that it is fully defined (only complete types may be used as non static attributes), which can cause further grief.
struct C {
struct Inner;
Inner foo; // error: field 'foo' has incomplete type
struct Inner { };
};
Though one could argue that Inner foo is a declaration and thus not covered by Stroustrup's quote.
I think the promise of free ordering inside the class is held if you split declaration and definition (into a header and an implementation file). Once you split them, the order really doesn't matter anymore.

Nested functions in C?

can any one tell me can we declare a function in user defined function ? such as
int sum(int x, int y)
{
int fun( float x);
}
Can we define a function inside a function ? As I know we can't define a function inside a function.
But I just did this and its work fine the code is given below :
{
int main()
{
func1();
return 0;
}
func1()
{
int i = 0;
auto func2()
{
i = 10;
printf("Heloo i am func 2\n");
}
printf("Heloo i am func 1\n");
func2();
}
}
It works very fine .
Now can anyone tell me what is going around how a function inside a function is defined or working properly ?
Can anybody explain to me why the code is working ?
Now when I changed few lines of code it give me following problems
The changes are following:
code:
{
func1()
{
func2();
int i = 0;
auto func2()
{
i = 10;
printf("Heloo i am func 2\n");
}
printf("Heloo i am func 1\n");
}
error:
error: static declaration of ‘func2’ follows non-static declaration
note: previous implicit declaration of ‘func2’ was here
Now what are these error and why are they coming ?
If I call func2() in main function than it will show an error like
undefined reference to func2
Now can anyone tell me what is wrong here ?
The C standard allows the declaration of functions within functions (as in your first code snippet), but not the definition of functions within functions (although some compilers may offer it as a non-standard extension).
The same is true for C++, although newer versions (C++0x, etc.) allow you to define anonymous lambda functions. But this is something different.
gcc allows this in C only (not C++) via -fnested-functions, but this is of course non-standard and non-portable so you should probably not use nested functions unless you have a very good reason.
This, for foo,
int main(void) {
int foo(void);
}
is not a definition of foo. It is a declaration and it is perfectly valid (though strange: function declarations belong outside any other functions) in C.
What C does not allow, which is what you found out, is that definitions cannot be nested.
/* INAVLID EXAMPLE */
int main(void) {
int foo(void) { return 0; }
}
When you call func2() before declaration, C assumes (according to standard) implicit declaration int func2(...), but when compiler finds func2() definition, it differs from previous implicit declaration, so compiler complains about it.
If func2() precedes the call to func2(), it acts as both definition and declaration, so no problem there.
And of course func2() cannot be called from main() as its scope is limited to func1(), like you cannot access local variable from another function.
As others mentioned, nested functions aren't standard in C, although some compilers (like GCC) support this feature.
This is just a supplement to Paul R's answer.
Assuming that your compiler is GCC,
the end of the
document
in Paul's answer says:
A nested function always has no
linkage. Declaring one with extern
or static is erroneous. If you need
to declare the nested function before
its definition, use auto
So func2 has to be declared as auto before the call of it.
If you change the second code
func1()
{
func2();
int i = 0;
...
to
func1()
{
auto func2(); /* declaration added */
func2();
int i = 0;
...
the code will be compiled.