C/C++ C++: Calling function in main.cpp from another .cpp file

  • Thread starter Thread starter JonnyG
  • Start date Start date
  • Tags Tags
    File Function
Click For Summary
The discussion revolves around an issue with calling functions defined in a class from a main.cpp file. The user encounters a scope error when trying to call the `absoluteVal` function, which is declared as a member of the `Chap` class in Chap.hpp. The solution involves correctly qualifying the function calls with the class instance, as well as defining the functions with the class scope in Chap.cpp. The user is advised to create an instance of the `Chap` class in main.cpp to access its member functions. Additionally, there is a discussion about the user's intent to learn about class structures and the distinction between member functions and standalone functions. The conversation also touches on C++11 features, particularly uniform initialization syntax, which the user learns about while troubleshooting their code. This highlights the importance of using modern C++ standards for better coding practices.
JonnyG
Messages
233
Reaction score
45
I am trying to call a function declared in a .hpp file and defined in the corresponding .cpp file, from my main.cpp file, but I keep getting an error. From what I have googled it seems as if I am doing this the right way, so I was hoping you guys could help out. Here's my code:

[CODE lang="cpp" title="Chap.hpp"]#ifndef CHAP_HPP
#define CHAP_HPP

class Chap
{
public:

double absoluteVal (double n) ;
unsigned fact (unsigned n) ;
};

#endif // CHAP_HPP[/CODE]

[CODE title="Chap.cpp"]#include "Chap.hpp"double absoluteVal (double n) {
return (n >= 0) ? n : -n;
}

unsigned fact (unsigned n) {
unsigned product {1};
for (unsigned i = 1; i <= n; ++i)
product *= i;
return product;
}[/CODE]

[CODE title="main.cpp"]#include <iostream>
#include "Chap.hpp"

using std::cout;
using std::cin;
using std::endl;

int main() {
cout << "Enter a number: ";
double n;
cin >> n;
cout << "The absolute value of " << n << " is " << absoluteVal(n) << endl;
return 0;
}[/CODE]

The error that I'm getting is:

C:/Users/J/Desktop/CPP/CppPrimer/CppPrimer/main.cpp: In function 'int main()':
C:/Users/J/Desktop/CPP/CppPrimer/CppPrimer/main.cpp:19:56: error: 'absoluteVal' was not declared in this scope

For what it's worth I am using the CodeLite IDE and a mingw-w64 compiler. I'd appreciate any help. Hopefully it's just me making a silly mistake.
 
Technology news on Phys.org
The functions absoluteVal and fact are declared in Chap.hpp as members of the class Chap.

Therefore when you define the functions in Chap.cpp, you need to name them as Chap::absoluteVal and Chap::fact.

Also, when you use the functions in main.cpp, you first need to declare an object of type Chap. Then you can call the functions as members of that object, for example:

C++:
    Chap myChap;
// ... your other stuff
    cout << "The absolute value of " << n << " is " << myChap.absoluteVal(n) << endl;

Disclaimer: I have not actually tried to compile and run your code with these corrections.

I'm curious about why you want to write a class that has member functions but no member data.
 
  • Like
Likes sysprog
This works. Thanks.

jtbell said:
I'm curious about why you want to write a class that has member functions but no member data.

I am going through C++ Primer. We are going over functions, so I write those two. I was then asked to create a header file with the function declarations in there. But then that got me thinking that I would like to remove my two functions (absoluteVal and fact) from my main.cpp file and put them in a .cpp file that corresponds to the header file I created. We haven't gone over classes in any detail yet. If I wanted to write a function (not a method - I am purposefully making this distinction), is the only way to include it in my main.cpp file? I feel like I may be asking a question for whose answer I may not be ready for yet.

EDIT: I just looked at the table of contents and in the next chapter we are going to cover classes and there is a section titled "defining nonmember class-related functions". I'm guessing that section will have my answer.
 
If you want to have separate header and implementation files for plain old functions, then toss out your class Chap from Chap.hpp and replace it with just the prototypes of the two functions:

C++:
#ifndef CHAP_HPP
#define CHAP_HPP

double absoluteVal (double n) ;
unsigned fact (unsigned n) ;

#endif // CHAP_HPP

Then you should be able to use the original versions of main.cpp and Chap.cpp.
 
  • Like
Likes sysprog and JonnyG
jtbell said:
Disclaimer: I have not actually tried to compile and run your code with these corrections.
That reminded me of this great line from Prof. Don Knuth (creator of ##\TeX##): Beware of bugs in the above code; I have only proved it correct, not tried it.
 
Haha, yeah, I was going out on a limb because because it's past my bedtime and I wanted to get to sleep.

But now that I'm hooked on this, I went ahead and set up the files for my suggested version in post #4. The following line in Chap.cpp:

unsigned int product {1} ;

gave me the message error: expected ';' at end of declaration. Looking more closely I noticed the {1} which I've never used for initializing a scalar variable. I've always done it as something like

unsigned int product = 1 ;

I thought, maybe this is something from C++11 and newer? I told my g++ to use -std=c++11, and sure enough it worked. So now I've learned something. :cool:

It makes sense to allow initialization this way, because it's consistent with list-initialization of arrays, etc.
 
  • Like
Likes sysprog
jtbell said:
Looking more closely I noticed the {1} which I've never used for initializing a scalar variable. I've always done it as something like

unsigned int product = 1 ;

I thought, maybe this is something from C++11 and newer? I told my g++ to use -std=c++11, and sure enough it worked. So now I've learned something. :cool:

It makes sense to allow initialization this way, because it's consistent with list-initialization of arrays, etc.
Yes, this is called uniform initialization syntax and was added in C++11. https://isocpp.org/wiki/faq/cpp11-language#uniform-init

It's 2020, and C++11 added many very good features that make many parts of the language easier and safer to use. I highly encourage you to always enable it (even better, C++14 or C++17). :smile:

In addition to providing a uniform syntax for initialization (as you noted, and as the name implies), it also has the advantage of disallowing implicit narrowing, so for example, lines 10 and 18 below are disallowed:
C++:
double myDouble {0.1};
uint32_t myUint32 {1};

// Error; assigning double-precision float to a single-precision float.
// Use
//    float myFloat {static_cast<float>(myDouble)};
// or
//    float myFloat = myDouble;
// instead.
float myFloat {myDouble};

// Error; assigning 32-bit integer to a 16-bit integer.
// Use
//    uint16_t myUint16 {static_cast<uint16_t>(myUint32)};
// or
//    uint16_t myUint16 = myUint32;
// instead.
uint16_t myUint16 {myUint32};
A couple of other notes: use of = with uniform initialization syntax is optional, so the following are equivalent:
C++:
int n {0};
int n = {0};
And empty braces provide default initialization, which calls the default no-argument constructor for class types, and zero-initialization for numerical types, so the following are equivalent:
C++:
int n {};
int n {0};
whereas of course this will result in an uninitialized variable, generally containing garbage:
C++:
int n;
 
Last edited:
  • Like
Likes sysprog

Similar threads

  • · Replies 8 ·
Replies
8
Views
2K
Replies
6
Views
2K
  • · Replies 39 ·
2
Replies
39
Views
5K
  • · Replies 8 ·
Replies
8
Views
4K
  • · Replies 22 ·
Replies
22
Views
3K
Replies
12
Views
2K
  • · Replies 5 ·
Replies
5
Views
3K
  • · Replies 36 ·
2
Replies
36
Views
6K
  • · Replies 40 ·
2
Replies
40
Views
3K
  • · Replies 33 ·
2
Replies
33
Views
3K