I am learning overloading an inline function.
In testing this code I can't compile with the following errors I can't understand as to what's wrong.
I tested it with only 1 inline function and works but a second breaks it. Can you please share some guidance:
Thank you for your help, Sergio
Compiler errors:
abs exception specification does not match previous declaration line 13
function long abs (const long) throw() already has body line 13
abs redefinition; different exception specification line 19
abs error in function definition or declaration; function not called line 30
abs error in function definition or declaration; function not called line 32
#include "pch.h"
#include <iostream>
using namespace std;
// Overload abs() three ways
inline int abs(int n)
{
cout << "In integer abs() \n";
return((n < 0) ? -n : n);
}
inline long abs(long n)
{
cout << "In long abs() \n";
return((n < 0) ? -n : n);
}
inline double abs(double n) {
cout << "In double abs() \n";
return ((n < 0 ? -n : n));
}
int main()
{
cout << "Absolute value of -10 Is ";
cout << abs(-10) << "\n";
cout << "Absolute value of -10L Is ";
cout << abs(-10L) << "\n";
cout << "Absolute value of -10.01 Is ";
cout << abs(-10.01) << "\n";
}
Your error is here:
using namespace std;
since this brings into the global namespace the definitions of the function overloads std::abs() (they are declared & defined in cmath which appears to be #included directly or indirectly into iostream), which then clash with your own definitions. The above statement (using namespace std;) is almost never a good idea, certainly not in a header file -- it is, unfortunately, commonly used in online coding contests to simplify code (no need for std::).
Btw, this has only do with inline inasmuch as the function definitions (not the declarations) clash, which must be declared inline in header files to obtain the proper linkage.
Precense of using namespace std; causes a conflict with ::std::abs function. However getting rid of using namespace std; will not solve the issue complitely.
The primary problem here is the use of a non-unique name for a function in global namespace. abs is a function from C standard library therefore you should not use this name for your own functions. Otherwise your may get an error if <stdlib.h> is included somewhere, or even a random Undefined Behavior because of ODR violation.
In order to prevent name conflicts in C++ you should typically define new functions in custom namespace:
n_sergio_solorzano_stuff
{
// Overload abs() three ways
inline int abs(int n)
{
...
or select globally unique names when you need to add something into global namespace:
inline int sergio_solorzano_stuff_abs(int n)
Related
I was writing a program of function overloading in Visual C++ 2010 .
Following is my code
// overload.cpp : Defines the entry point for the console application.
#include<Windows.h>
#include<iostream>
#include<conio.h>
using namespace std;
//abs is overloaded in 3 types
int abs(int i);
double abs(double d);
long abs(long f);
void main()
{
cout<<abs(-10)<<"\n";
cout<<abs(-11.0)<<"\n";
cout<<abs(-9L)<<"\n";
getch();
}
int abs(int i)
{
cout<<"using integer abs()\n";
return i>0? -i:i;
}
double abs(double d)
{
cout<<"using double abs()\n";
return d>0? -d:d;
}
long abs (long l)
{
cout<<"using long abs()\n";
return l>0?-l:l;
}
I am having problems in double abs and long abs function that
1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(22): error C2084: function 'double abs(double)' already has a body
1>c:\users\abc\documents\visual studio 2010\projects\overload\overload\overload.cpp(26): error C2084: function 'long abs(long)' already has a body
Why this problem is coming?
I have changed the compilation from c to c++
but recently I ran an other program for overloading,it worked.I don't know how? here is the code.
#include<iostream>
#include<cstdio>
#include<conio.h>
#include<cstring>
using namespace std;
void stradd(char*s1,char*s2);
void stradd(char*s1,int i);
void main()
{
char str[80];
strcpy(str,"hello");
stradd(str,"there");
cout<<str<<"\n";
getch();
}
//concatenate a string with a "stringized "integer
void stradd(char*s1,int i)
{
char temp[80];
sprintf(temp,"%d",i);
strcat(s1,temp);
}
//concatenate 2 strings
void stradd(char*s1,char *s2)
{
strcat(s1,s2);
}
and output is hellothere
Your problem comes from a header in which abs is declared for some types such as double. You're not allowed to have to functions with exactly the same header (that is, same return type, same name, same list of parameters, same qualifiers such as const).
There are two ways of avoiding this:
Use the standard library: std::abs is good, you don't need to implement it yourself
Naming the method absoluteValue or myAbs or whatever you like, but not abs
A third way, namely removing using namespace std does not work according to your comment. This is because you include Windows.h. This itself includes a bunch of headers, probably including math.h. This gives a method called abs in the global namespace. Better don't include Windows.h and include cmath if you need to. Then, abs is only declared in namespace std, hence you can call it with std::abs and is different from abs.
When overload resolution cannot select one function as the unique best match, the call is ambiguous. An ambiguous call produces a compilation error.
In std there is already an abs() with the following signature:
int abs (int n);
So while you try to overload it with double and long it results in ambiguity for the compiler.
If you're a beginner learning about coding i suggest you to use function names not defined in libraries (at least the ones you have included).
stefan have already given the solution to it:
Remove using namespace std; and explicitly write std::cout
OR
Re name your function to absoluteValue or something else
OR
Use explicit namespaces in function declaration and calls. (Not tested, though it should work)
Put your function inside a class or namespace.
Maybe this would provide you with a little insight (From SO).
EDIT:
The second question's overloaded functions stradd() is not defined in any other library. That is why no Compilation Errors. The following function signature in your code will result an error: char * strcat ( char * destination, const char * source )
Your primary problem is that you use global namespace. Just declare your function in your own namespace and all name collisions will be gone.
Let me explain why you're getting those compile-time errors.
Somewhere in the headers you included there are double abs(double) and long abs(long) functions. Then you're creating functions with the same signatures by your own. So compiler just don't know what to use when you'll call one of them - there are 2 pairs of equal functions. So it refuses to compile that, and you're getting those errors.
So you have 2 choices - hope that every time you'll want to create a function you will choose an unique name, or just create a namespace and your function names should be unique only to another functions in your namespace.
And it's not about overloading - void func(int i) overloads void func(float f), but void func(int i) overrides void func(int i). You can override superclass member functions in subclasses, but you cannot override standalone functions like abs().
just change abs function name with another.
abs() is a keyword therefore it is showing errors.
My function test is added to two different .cpp-files and the functions are private to their respective files as shown below
test1.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
test2.cpp
#include <iostream>
using namespace std;
void test()
{
cout << "test" << endl;
}
main.cpp
#include <iostream>
using namespace std;
int main()
{
return 0;
}
During linking I get the error multiple definition of test() - but how is that possible, considering that the two files have their own private scope!? I could understand it if I included the function prototype in each .cpp-files' corresponding header, but there is no such thing in this example.
You need the inline keyword for that:
inline void test()
{
cout << "test" << endl;
}
This allows you to have multiple definitions in separate source files without violating the one-definition rule. However, note that the function still has external linkage and they will all resolve to the same address. Also:
An inline function shall be defined in every translation unit in which
it is odr-used and shall have exactly the same definition in every
case
If you want separate functions with different addresses (internal linkage), use the static keyword instead.
Both test functions are in the same global namespace of the program. In order to avoid error you may:
1) wrap any or both functions in namespace:
namespace A
{
void test()
{
...
}
}
2) use static keyword
3) just rename one of them
Add static in each test function.
#include <iostream>
using namespace std;
static
void test()
{
cout << "test" << endl;
}
To elaborate on above answers:
In C++, function declarations can be repeated as many times as you want. A function definition however (i.e. the function body), can occur only once.
When creating your binary, the compiler compiles each file to a obj file so in your example you end up with test1.obj, test2.obj and main.obj. After all files compiled successfully, the linker links them together to create your executable. This is where multiple definitions for the same function are found and why linking fails.
Depending on what you want, you can do the following to resolve this:
If you want multiple different functions with the same name, then you have to disambiguate them. C++ wouldn't be C++ if you only had one way to do this:
The old c way: use the static keyword
Use an anonymous namespace
Use a namespace
If you want only one function:
Separate the definition from the declaration, i.e. put the declaration in a header file and move the definition to a source file.
Define the function as inline in a header
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
C++: Easiest way to access main variable from function?
I need to get my variable "input" from my main function in a.cpp to another function named check in b.cpp. I looked into it on Google and this forum/thingy, and I found you could do it with global variables using extern, but that's it's also bad to use those and I couldn't find an answer to what an alternative is? How should I transfer the data in the variable to the other function without using globals?
Code of how I got arguments to work.
(What I'm trying to do here is a console "manager" for solutions of project Euler which I can call to solve/view via input, I started working on the code 40 mins ago.)
main.cpp
#include <iostream>
#include <windows.h>
#include "prob.h"
using namespace std;
int check(string x);
int main()
{
string input = "empty";
clear();
cout << "Welcome to the Apeture Labs Project Euler Console! (ALPEC)" << endl << endl;
cout << "We remind you that ALPEC will never threaten to stab you" << endl;
cout << "and, in fact, cannot speak. In the event that ALPEC does speak, " << endl;
cout << "we urge you to disregard its advice." << endl << endl;
cin >> input;
cin.get();
check(input);
cout << input << endl;
cin.get();
return 0;
}
prob.h
#ifndef PROB_H_INCLUDED
#define PROB_H_INCLUDED
int main();
int clear();
int check();
int back();
int P1();
int P2();
int P3();
int P4();
#endif // PROB_H_INCLUDED
back.cpp
#include <iostream>
#include <windows.h>
#include "prob.h"
using namespace std;
int clear()
{
system( "#echo off" );
system( "color 09" );
system( "cls" );
return 0;
}
int check( string x )
{
if( x == "help" );
if( x == "empty" )
{
cout << "And.... You didn't enter anything..." << endl << endl;
}
else
{
cout << "Do you have any clue what you are doing? " << endl << endl;
}
return 0;
}
By passing the data as an function argument.
For example:
int doSomething(int passedVar)
{
}
int main()
{
int i = 10;
doSomething(i);
return 0;
}
Note that the function definition may reside even in a different cpp file. The main only needs to see the function declaration, and the linker shall link the function definition correctly.
Usually, one would add the function declaration in a header file and include the header file in main, while providing the function definition in another cpp file.
The code you show has number of problems:
You do not need to declare main in the header file.
Your function declaration and definition of check() do not match. Your header file says it takes no argument and you define a the function definition to take one argument. Obviously, they don't match. As they stand now they are two completely different functions.
As the compiler sees it you declared one function who's definition you never provided and you defined another function in the cpp file. Thus the function declared(one with no parameters) was never defined and hence the definition not found error.
Andrei Tita is absolutely correct. If you have a "value" in one module (e.g. "main()" in a.cpp), and you wish to use that value in a function (e.g. "foo()" in b.cpp) ... then just pass that value as a function argument!
As your programs become more sophisticated, you'll probably start using classes (instead of functions) .
ns.cpp:
#include <iostream>
namespace ns { // want to access this globally
class A ;
}
class ns::A {
public:
int x1;
char s1[128];
};
int main()
{
int doit();
//using namespace ns;
ns::A a;
a.x1= 2;
std::cout << "pre " << a.x1 << "\n" ;
doit();
std::cout << "post " << a.x1 << "\n" ;
}
ns_call.cpp:
namespace ns {
class A;
}
class ns::A {
public:
int x1;
char s1[];
};
using namespace ns;
int
doit()
{
extern ns::A a;
a.x1= 100;
}
in ns.cpp, a class is declard within a namespace.
the class is defined followed.
Variables in the class are to be accessed globally. This
is the goal of the namespace.
ns_call.cpp then access 1 of the class' member, x1.
The 2 files were compiled OK with gcc 5.4.1 in Fedora 14.
run output is:
pre 2
post 2
I expected 'post 100' because i wanted to access int x1 in class A
globally.
None of extern, namespaces or forward declarations seem to mean what you think they mean.
If you want to introduce a name that can be accessed my multiple translation units (what you seem to mean when you say "globally"), you put those definitions in a header file, and #include that header from wherever you want to use it.
What you're actually doing is introducing class A over and over again in every translation unit (eg, in each CPP file). This is a violation of the ODR at best.
I'm just gonna help you fix your problem, while you absolutely have to heed the other answers about ODR (One Definition Rule) and fix your design.
in the ns.cpp file, you have to move the line ns::A a; out of the main() function. Put it at the file scope (e.g. right before main.) Also, in the ns_call.cpp file, move the line extern ns::A a; out of the function too.
Note: you may or may not have to do the second part, and this whole method might or might not work. I don't have access to a compiler right now.
Again I have to agree with other comments that this design is flawed and it will cause you headaches.
I am new to templates in c++.
i was trying some small programs.
CPP [80]> cat 000001.cpp 000001.hpp
#include <iostream>
#include <string>
#include "000001.hpp"
int main()
{
int i = 42;
std::cout << "max(7,i): " << ::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << ::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << ::max(s1,s2) << std::endl;
}
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
when i compile this program:
i get an error below:
CPP [78]> /opt/aCC/bin/aCC -AA 000001.cpp
Error (future) 229: "/opt/aCC/include_std/string.cc", line 164 # "Ambiguous overloaded function call; a
function match was not found that was strictly best for ALL arguments. Two functions that matched
best for some arguments (but not all) were "const unsigned long &max<unsigned long>(const unsigned
long &,const unsigned long &)" ["000001.hpp", line 2] and "const unsigned long &std::max<unsigned
long>(const unsigned long &,const unsigned long &)" ["/opt/aCC/include_std/algorithm", line 1762]."
Choosing "const unsigned long &max<unsigned long>(const unsigned long &,const unsigned long &)"
["000001.hpp", line 2] for resolving ambiguity.
_C_data = _C_getRep (max (_RW::__rw_new_capacity (0, this),
^^^
Warning: 1 future errors were detected and ignored. Add a '+p' option to detect and fix them before they become fatal errors in a future release. Behavior of this ill-formed program is not guaranteed to match that of a well-formed program
Could nybody please tell me what exactly the error is?
You are probably including <iostream.h> instead of <iostream> somewhere. The former hasn't existed for some time now, but for compatibility reasons, you compiler still accepts the include and replaces it with
#include <iostream>
using namespace std;
This causes std::max to be brought to the global namespace, thus resulting in an ambiguity. Replace <iostream.h> with <iostream> or rename your max function and the problem should disappear.
Edit: You've apparently fixed the include, but I bet you still have using namespace std; somewhere. You need to get rid of that. In fact you should never use using namespace in the global scope.
Edit: You might also have using std::max somewhere. You need to get rid of it too.
The code you've posted compiles just fine, there must be something else that is wrong inside "000001.hpp". Can you post the contents of that file too?
Edit: If you do as avakar says but the problem persists, that must be due to some problem with your compiler. There are two obvious workarounds I can think of: rename your max function to something else, or put it in a namespace:
namespace Foo
{
template <typename T>
inline T const& max (T const& a, T const& b)
{
return a < b ? b : a;
}
}
int main()
{
int i = 42;
std::cout << "max(7,i): " << Foo::max(7,i) << std::endl;
double f1 = 3.4;
double f2 = -6.7;
std::cout << "max(f1,f2): " << Foo::max(f1,f2) << std::endl;
std::string s1 = "mathematics";
std::string s2 = "math";
std::cout << "max(s1,s2): " << Foo::max(s1,s2) << std::endl;
}
I don't know which compiler you are using but the second error tells you that the two following functions are clashing :
::max
std::max
It seems really weird, you may have a using namespace std; somewhere or worse, that one of your include use iostream.h as noted in the first error. Could you give more information about your compiler/toolchain and the content of your .hpp file?
It says that two definitions for
max<unsigned long>
were found. One definition is in 000001.hpp and the other is in /opt/aCC/include_std/algorithm. The compiler chose the one in 000001.hpp for now, so no error is present now. But it says that these two definitions may cause errors in the future.
I don't know if this causes the problem, but anyhow; you shouldnt use the name max for your global (or local) function as it is a part of STL.