How to overload a function in a header file ?

Suppose I have a main.cpp,


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//main.cpp
//simplest form

#include <whatever necessary>
#include "header.h"

int main()
{

    type1 a1, b1;
    type2 a2, b2;

    a1 = func(b1);
    a2 = func(b2);  


  return 0;
}


and header.cpp and also corresponding header.h .

Am I allowed to do the following ?



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//header.cpp
#include <whatever needed>
#include "header.h"

type1 func(type1 input)
{
   type1 output = something with input;

   return output;
}


type2 func(type2 input)
{
   type2 output = something with input;

   return output;
}


1
2
3
4
5
6
7
8
//header.h
#ifndef HEADER_H
#define HEADER_H

type1 func(type1 input);
type2 func(type2 input);

#endif 


If this is not allowed then what would be the right way to proceed ?
My aim is to finally link them and create a single executable file.

My system info:

g++ 4:5.3.1-1ubuntu1 amd64 GNU C++ compiler

Ubuntu 16.04
Last edited on
Have you tried compiling it and seeing what happens?
I did try and there errors but now I know that was because of my stupidity ! I passed a wrong linking command in the terminal.. my bad !!

So to correct myself and also to help a future newbie like myself, I am going to write down all the codes as an atonement. Here we go:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//main.cpp
#include <iostream>
#include "func.h"

int main()
{
    
    int a1, b1 = 2;
    double a2, b2 = 3.5;

    a1 = func(b1);
    a2 = func(b2);

    std::cout << "a1, a: " << a1 << ", " << a2 <<"\n";


    return 0;
}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//header.cpp

#include <iostream>
#include "func.h"

int func(int a)
{

    //input = output (Identity function)

    return a;

}


double func(double a)
{

    //input = output (Identity function)

    return a;

}


1
2
3
4
5
6
7
8
9
//func.h

#ifndef HEADER_H
#define HEADER_H

    int func(int a);
    double func(double a);

#endif 



To compile I would do:

g++ main.cpp func.cpp -o overload

and can be executed using: ./overload .
Last edited on
To compile I would do:

g++ main.cpp func.cpp -o overload


Always compile with a high level of warnings; compile against the latest standard that you have:

g++ -std=c++14 - Wall -Wextra -pedantic-errrors main.cpp func.cpp -o overload.

C++14 is the latest current standard, but c++17 is due out soon.

There are other useful warnings that are enabled despite the seemingly comprehensive options above:

http://www.cplusplus.com/forum/general/183731/#msg899203

Warnings are your friend, they tell you about potential problems with your code. Just because something compiles, doesn't mean that the program is correct.

Often one may use *.cpp rather than specify each individual cpp file: hopefully you have all the files for a particular project in one directory.

I like to use *.hpp for header files - it means a header file with cpp code inside, as opposed to *.h which could mean a C header file. This is a personal preference, which I find useful.

Good Luck !!

I've just realized that the reason behind my question wasn't as naive as my question was ! Actually I put it in a wrong way, my question was supposed to be about two functions sharing the same name with same input types but different output types and this shows "error: ambiguating new declaration of" ! So going back to the beginning I would like to repeat the question:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//main.cpp
#include <iostream>
#include "func.h"

int main()
{
    
        int a1, b1 = 2;
        double a2, b2 = 3.5;

        a1 = func(b1);
        a2 = func(b2);

        std::cout << "a1, a: " << a1 << ", " << a2 <<"\n";


        return 0;

}





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//header.cpp
#include <whatever needed>
#include "func.h"

type1   func( type1  input )
{
       type1 output = something with input;

       return output;
}


type2   func( type1  input )
{
       type2 output = something with input;

       return output;
}




and


1
2
3
4
5
6
7
8
9
//func.h
#ifndef FUNC_H
#define FUNC_H

type1   func(type1 input);

type2   func(type1 input);

#endif  



From my limited knowledge I know that function overloading has to do with two functions that share the same name but accepts different (data) types of arguments, or different number of arguments and maybe also different return types. In the above case I have func (type1) in both cases, same data type argument but different return type. The compiler doesn't allow this... and throws some strange "ambiguating new declaration". I don't know how to proceed. One ugly solution will be to insert another fake argument in one of the func s... so that the arguments are different, but I don't like it.
One ugly solution will be to insert another fake argument in one of the func s... so that the arguments are different, but I don't like it.


It sounds to me that the functions need to have different names? What is the real world situation?
Different names of course will solve the thing but then there's no question of overloading. I have two kinds of string(s), an std::string and another CERN's ROOT string called a TString (https://root.cern.ch/doc/v608/classTString.html). They both keep occuring all the time and I need play around so I need to overload one function name that can take both kinds of strings etc... just like we overload an addition (of two numbers double or int ) function when learning c++ for the first time.
I have two kinds of string(s), an std::string and another CERN's ROOT string called a TString


Then you have 2 different types, hence no problem with overloading. Disambiguate by specifying the namespace that each type is in:

std::string func(std::string& Var1);

TString func(TStringNamespace::TString& Var2);


Edit: removed a comment.

Good Luck ! :+)
Last edited on
I t looks like i have said the wrong thing in my last post. However your code for main.cpp is different to the other two snippets.

With the different return types - why do you need to do this? Can you use TString for everything? Can TString be constructed from a std::string? Why is there a perception that you have to use both types?

Essentially what you are asking is a conversion question, can you do that outside the function?

Your link 404'd for me, so I don't know the details about the TString type.
Thanks for your reply. But I need same input type, both std::string, it's the output that differ. Currently I am relying on std::stringstream to convert one to the other kind as a temporary solution.
Last edited on
About warnings during compilation, actually its my fault... I already created an alias:

alias g++='g++ -Wall -Wextra -Werror -pedantic -std=c++14' so sometimes forget to mention.
But I need same input type, both std::string, it's the output that differ.


As you have already guessed, one can't do that - which function should the compiler call?

I still think (guessing) there may be no need to use both types. For example in Qt, there is QString. One does everything with that and doesn't use std::string at all.
there may be no need to use both types... in Qt, there is QString. One does everything with that and doesn't use std::string at all.


my interpretation of this would be that either Qt users use a conversion rule of some kind or they have all the features of std::string already in QString , in the latter case, maybe it's also true for TString but I am not an expert and I don't know how various members of std::string translate to the TString , so my solution will be the conversion. My situation is the following:

Inbuilt ROOT functions always take TString as arguments, for example to open a *.root file it uses the syntax Tfile.Open(TString); and doesn't accept std::string, but I need std::string for many other things because I am not interested to work entirely within CERN's ROOT, I am just interested in a few of their libraries and because I need to analyze data stored in *.root files, I do need std::string for most part. Hence my workaround will be to use std::stringstream to convert one type to the other and hence I can always work with std::string.
Hence my workaround will be to use std::stringstream to convert one type to the other and hence I can always work with std::string.

Why? A std::string should be directly constructable from a TString since TString overloads operator const char*. A TString can be constructed from a std::string if you call the std::string's data or c_str method. Why would a stringstream need to be involved?
I am just a beginner and my knowledge is very limited, I haven't tried c_str() on a TString yet but my guess is that compiler will complain. Consider the following program that takes a filename "file.root":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

int main(int argc, char* argv[] )
{
/*

argv[1] definitely cannot be a TString in a main, I need to use argv[1] in the following ways:
 
  1. a TString so that ROOT libraries can handle it... opening TFile etc.
  2. the input can be a full path .. very long including "/" s, I want to strip everything off
       except the final file name so that later I can use it to create another "ROOT" file 
       somewhere else that has to be "TString" again. For stripping the path I will be using  
      "find_first_of("/");"  and other related things as these are the methods I have learned 
       so far and they need to work with std::string.    

*/

return 0;
}



I understand that there can be other better ways to solve my problem but I would really like to know the limits of function overloading for the sake of knowledge. Today I tried the following:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//func.cpp
#include "func.h"
#include "TString.h"
#include <whatever else needed>

// first function takes TStrings returns std::string

std::string  func( TString input )
{

std::string output;

//function body

return output;
}


// second function takes  std::string and returns TStrings

TString  func( std::string input )
{

TString output;

//function body

return output;
}




1
2
3
4
5
6
7
8
9
10
//func.h
#ifndef FUNC_H
#define FUNC_H
#include "TString.h"
#include <whatever else needed>

std::string  func( TString input );
TString  func( std::string input );

#endif 



And the compiler complains about "overloading ambiguity", I don't understand which part is ambiguous ! Functions inputs are of different types as well as the out put types. I would like to learn why is this not permitted.
Last edited on
my interpretation of this would be that either Qt users use a conversion rule of some kind or they have all the features of std::string already in QString , in the latter case, maybe it's also true for TString but I am not an expert and I don't know how various members of std::string translate to the TString , so my solution will be the conversion.


For
QString
it's the latter case; it has all the same functionality as std::string. Qt has technical reasons for doing so, mainly to do with Qt's use of the Meta Object Compiler (MOC)

As cire mentioned, one can construct a TString from a std::string. And there is lots of functionality in TString, as I asserted earlier, you can use that almost exclusively.

https://root.cern.ch/doc/master/classTString.html#a2fb70d94c8fdba6d90145a01aec1ce3f

Your code compiles for me, you didn't include <string>. As I keep saying, there is no need for function overloading at all.
closed account (48T7M4Gy)
FWIW http://doc.qt.io/qt-5/qstring.html#fromStdString and the corresponding TString constructor in previous post. There's no need to breach data-hiding practice.

Like Qt, CERN ROOT is more or less a pile of wrapper-like objects/classes via the underlying C++, C. Neither is probably a good way to learn C++ and then adapt without a clear understanding of C++ (maybe even C).

Otherwise it's not unlike learning C++ via MFC - very difficult :)
hi,
about function overloading, it depends on parameters
consider this:
1
2
void func(int a);
int func(int a);

compiler gives error because we have 2 functions with the same parameters
now this:
1
2
void func(int a);
void func(float a);

error because same number of parameters
1
2
void func( int a, int b);
void func(double a);

this is correct and will compile fine
if you want to know more, read about function mangling in C++
TheIdeasMan (4983)

Your code compiles for me, you didn't include <string>. As I keep saying, there is no need for function overloading at all.
, I did include everything :) #include <whatever else needed> that includes <string> too.


@kemort
Neither is probably a good way to learn C++ and then adapt without a clear understanding of C++ (maybe even C).
, true that.. that's why I am trying to work with the minimum number of possible ROOT objects for the sake of using the data analysis features of ROOT, I have even quit using their compiler CINT/ACLiC (whatever it is).


@heepoo (114), my inferences based on your examples will be:
1. sama input type, different return type : error.
2. same return type, different input type: error
3. different input types, different number of inputs, same return type : good.

But that doesn't exhaust everything:
there can be cases of:

4. different number of inputs, different return types, I am guessing this case will work out just fine as you stressed on the different number of inputs.

Does this mean as long as the number of input parameters don't match, everything else can be whatever I wish them to ?

Thanks for the suggestion
read about function mangling in C++
, I will read about it.
Topic archived. No new replies allowed.