Sarwan Shah
Sarwan Shah

Reputation: 23

Function call from external file C++

I am trying to call a function from an external file to a source file. However, when I do so I'm getting the following error:

Build Error Visual Studio C++

Why am I getting the following errors? I've been trying to get my head around it all day, but it has all been in vain. P.S I'm am very new to the language and programming in general. Past experience: Python

source.cpp

#include <iostream>
#include <string>
#include "func.cpp"
using namespace std;

double pow(double x, int y);

int main()
{
    double x;
    int y;
    double answer;

    cout << "Choose a number: " << endl;
    cin >> x;
    cout << "Raised to the power: " << endl;
    cin >> y;

    answer = pow(x, y);

    cout << "Answer: " << answer << endl;

    return answer;
}

func.cpp

double pow(double x, int y)
{
    double result = 1;
    if (x == 0 && y == 0)
    {
        result = -1;
    }
    else
    {
        if (y == 0)
        {
            result = 1;
        }
        else if (y < 0)
        {
            x = 1.0 / x;
            y *= -1;
        }
        for (int i = 0; i < y; i++)
        {
            result *= x;
        }

    }

    return result;
}

Upvotes: 1

Views: 1528

Answers (2)

user4581301
user4581301

Reputation: 33982

A couple things going on here. The most immediate is one of the header's you've included is declaring pow or std::pow. As much as I'd like to blame it all on using namespace std;, the good ol' C pow function is good enough to derail the compiler. The compiler finds two pows with similar enough parameters and doesn't know which one to use. Instead name your function mypow or place it in your own namespace.

Eg: func.cpp

namespace my
{ 
    double pow(double x, int y)
    {
        // guts of pow are unchanged
    }
}

and in source.cpp

double pow(double x, int y);

becomes

namespace my
{ 
    double pow(double x, int y);
}

and is called

answer = my::pow(x, y);

That solves problem 1.

Problem 2 is a linker problem you haven't seen yet. In your project func.cpp is going to be compiled to func.obj. func.cpp is also included in source.cpp. An included function is effectively pasted into the including file so, you now have two copies of everything in func being compiled. pow can be found inside func.obj and source.obj.

This becomes a problem when the linker tries to assemble func.obj and source.obj into a single executable file. the Linker finds two pows and, similar to the compiler, doesn't know which to use.

The standard rule of thumb is do not include cpp files. Let the compiler compile them and the linker link them. Create a header that exposes the functions in the cpp file that need to be used externally and have the users include the header.

This make your program look like

func.h

#pragma once
namespace my
{
    double pow(double x, int y);
}

func.cpp

namespace my
{ 
    double pow(double x, int y)
    {
        double result = 1;
        if (x == 0 && y == 0)
        {
            result = -1;
        }
        else
        {
            if (y == 0)
            {
                result = 1;
            }
            else if (y < 0)
            {
                x = 1.0 / x;
                y *= -1;
            }
            for (int i = 0; i < y; i++)
            {
                result *= x;
            }

        }

        return result;
    }
}

source.cpp

#include <iostream>
#include <string>
#include "func.h"
using namespace std;

int main()
{
    double x;
    int y;
    double answer;

    cout << "Choose a number: " << endl;
    cin >> x;
    cout << "Raised to the power: " << endl;
    cin >> y;

    answer = my::pow(x, y);

    cout << "Answer: " << answer << endl;

    return answer;
}

Unrelated, but good reading: Why is "using namespace std" considered bad practice?

Upvotes: 4

Caleb Evans
Caleb Evans

Reputation: 25

Here is all you need to do in order to fix the issue:

Step 1-

change the second c++ file into a c++ header file by changing the extension to '.hpp' and in the other file.

Step 2-

remove line 6 from source.cpp

The above should fix your issue.

Upvotes: 0

Related Questions