Why can't I use my function in the header file? - c++

main.h: header
#ifndef _MAIN_H
#define _MAIN_H
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
typedef struct ComplexNum
{
double real;
double img;
}mc;
char *JustShow(mc );
#endif // _MAIN_H
cal.cpp : function defined in another file called
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
char *JustShow(mc a)
{
char str1[100];
char str2[100];
char str3 [100];
sprintf(str1,"%f",a.real);
sprintf(str2,"%f",a.img);
strcat(str1," + ");
strcat(str1,str2);
strcat(str1,"i");
return(str1);
}
I tried to use the JustShow function in another file, but the compiler said undefined reference to 'JustShow'
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include "main.h"
int main()
{
mc y;
y.img = 4;
y.real = 3;
printf("%s",JustShow(y));
}
I am so confused why can't I use the function JustShow when I had already added "main.h". I am also confused why should we define the functions in the source file instead of the header.
I'm sorry if this is the basic knowledge I should learn about and not ask others.

I'm going to call the third piece of code "main.cpp".
why can't I use the function JustShow when I had already added "main.h".
Header files only inform a compiler that a function, variable or constant exist. You need to compile cal.cpp with main.cpp: g++ main.cpp cal.cpp -o main
I am also confused why should we define the functions in the source file instead of the header.
It makes code more organised.
It speeds up compile time.
You can read more about header files here
Some advice for your code:
Function JustShow is incorrect. Arrays are just pointers and you are returning a pointer to a local variable that are deleted after function returns. It means that it will be overwritten and you will lose data there (and trying to write there may crash your program). In order to make it work you can:
Give an array as an argument to the function. Then we would have void JustShow(mc a, char* str1);
create new array with new (or malloc if you wirte in C, not C++).
You don't need to concat so much. sprintf can do all of that:
void JustShow(mc a, char* str1) {
sprintf(str1,"%f + %fi", a.real, a.img);
}

Related

Using static const string[] as a member instead of a global, initialized in the .cpp file

Related to this. I'd like to avoid using global variables so I resorted to using structs with enum and std::string[] (see link) in order to build menus for a small application. I would also like to have these enums in a separate header file. The selected answer in the link implies using --std=c++17, which I'd like to avoid, at least for now, and decided to use a static const std::string[] -- no need to include extra array or vector since this is initialized once, never modified, only called, ALL is always known.
As other answers on this have made it clear, I need to either initialize A::names outside the struct, or use a static const std::string& setter (see this, for example). But all the answers so far dealt with a std::string, not an array, std::string[].
This is a simple example of what I tried. It simply tries to print the contents of A::names using a for() loop iterating through the enum in struct A:
a.h:
#ifndef A_H_INCLUDED
#define A_H_INCLUDED
#include <string>
struct A
{
enum E { ONE, TWO, ALL };
static const std::string names[ALL];
};
#endif // A_H_INCLUDED
a.cpp:
#include "a.h"
static const std::string A::names[A::ALL] { "one", "two" };
main.cpp:
#include "a.h"
#include <iostream>
int main()
{
for(int i=A::ONE; i<A::ALL; ++i)
std::cout << A::names[i] << '\n';
return 0;
}
The error after g++ main.cpp is:
main.cpp:(.text+0x24): undefined reference to `A::names[abi:cxx11]'
collect2: error: ld returned 1 exit status
Seeing the cxx11, I thought g++ --std=c++11 main.cpp would solve it, but it doesn't.
So, what am I doing wrong, or, how could I adapt the version with the setter to return an array, std::string[]? My goal is to have an alternative to a global variable, that has only one instance in memory no matter how many calls.
Here's an adapted code, from a small program, on how I would build a menu using struct with enum and string (menu_design = new QMenu... and menuDesignAction() is the function that updates):
for(unsigned char i=0; i<A::ALL; ++i) // needs initializing
{
QAction *tmpAction {new QAction(tr(A::names[i].c_str()))};
tmpAction->setObjectName(QString("%1").arg(i));
connect(tmpAction, SIGNAL(triggered(bool)), this, SLOT(menuDesignAction()));
menu_design->addAction(tmpAction);
}
As a side-note, in the snippet above, I have to use .c_str(), but I am using a std::string in the enum. If I could make it *char[] instead of std::string[], would I avoid extra calls? If I am not wrong, how could the answers to my problem (assuming there are) be adapted so as to be able to fit somehow in the Qt snippet?

Cannot Compile .cpp File When Trying To Define Private Var

I am attempting to compile a .cpp file that includes a .h file and then implements the class outlined.
In String.h:
using namespace std;
class String
{
private:
int _length;
char *data;
int getCharArraySize(char arr[]);
In String.cpp:
#include "String.h"
using namespace std;
/*
* Private vars and methods
*/
int String::_length;
char String::*data;
int String::getCharArraySize(char arr[])
{
//method body
return 0;
}
When I attempt to compile with g++ I get this error:
% g++ String.cpp -c
String.cpp:14:17: error: ‘int String::_length’ is not a static data member of ‘class String’
int String::_length;
I am only having issues with String::_length. I was initially thinking that it was due to _length being private but all the other private methods/vars, compile just fine. I also need to leave this .h file as is so I cannot just make it public. Any help would be appreciated!
Well, it's exactly as the compiler says: _length is not a static member variable. Yet, you are treating it as one by providing it with its own definition. Simply do not do that. Only static member variables should be defined like that.
The same goes for data.
By the way, if you do ever have to define a char* variable, then this is wrong:
char String::*data;
and this is right:
char* String::data;
Lexical grammar production oddities (inherited from C) notwithstanding, the * is part of the type, not the name.

How to make a variable available to multiple .cpp files using a class?

This question has derived from this one.
I have a working program which must be split into multiple parts. In this program is needed to use a variable (now it's a GTK+ one :P) many times in parts of the program that will end up in separated .cpp files.
So, I made a simple example to understand how to make variables available to the program parts. A modified version of the previous code would be:
#include <iostream>
using namespace std;
int entero = 10;
void function()
{
cout<<entero<<endl;
//action1...;
}
void separated_function()
{
cout<<entero<<endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
It is needed to split the code correctly, to have function(), another_function() and main() in separated .cpp files,and make entero avaliable to all of them... BUT:
In the previous question #NeilKirk commented:Do not use global variables. Put the required state into a struct or class, and pass it to functions as necessary as a parameter (And I also have found many web pages pointing that is not recommended to use global variables).
And, as far I can understand, in the answer provided by #PaulH., he is describing how to make variables avaliable by making them global.
This answer was very useful, it worked fine not only with char arrays, but also with ints, strings and GTK+ variables (or pointers to variables :P).
But since this method is not recommended, I would thank anyone who could show what would be the correct way to split the code passing the variables as a function parameter or some other method more recommended than the - working - global variables one.
I researched about parameters and classes, but I'm a newbie, and I messed the code up with no good result.
You need to give the parameter as a reference if you want the same comportement as a global variable
#include <iostream>
using namespace std;
// renamed the parameter to avoid confusion ('entero' is valid though)
void function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value
//action1...;
}
void separated_function(int &ent)
{
cout<<ent<<endl;
++ent; // modify its value again
//action2...;
}
int main( int argc, char *argv[] )
{
int entero = 10; // initializing the variable
// give the parameter by reference => the functions will be able to modify its value
function(entero);
separated_function(entero);
cout<<entero<<endl;
//something else with the mentioned variables...;
return 0;
}
output:
10
11
12
Defining a class or struct in a header file is the way to go, then include the header file in all source files that needs the classes or structures. You can also place function prototypes or preprocessor macros in header files if they are needed by multiple source files, as well as variable declarations (e.g. extern int some_int_var;) and namespace declarations.
You will not get multiple definition errors from defining the classes, because classes is a concept for the compiler to handle, classes themselves are never passed on for the linker where multiple definition errors occurs.
Lets take a simple example, with one header file and two source files.
First the header file, e.g. myheader.h:
#ifndef MYHEADER_H
#define MYHEADER_H
// The above is called include guards (https://en.wikipedia.org/wiki/Include_guard)
// and are used to protect the header file from being included
// by the same source file twice
// Define a namespace
namespace foo
{
// Define a class
class my_class
{
public:
my_class(int val)
: value_(val)
{}
int get_value() const
{
return value_;
}
void set_value(const int val)
{
value_ = val;
}
private:
int value_;
};
// Declare a function prototype
void bar(my_class& v);
}
#endif // MYHEADER_H
The above header file defines a namespace foo and in the namespace a class my_class and a function bar.
(The namespace is strictly not necessary for a simple program like this, but for larger projects it becomes more needed.)
Then the first source file, e.g. main.cpp:
#include <iostream>
#include "myheader.h" // Include our own header file
int main()
{
using namespace foo;
my_class my_object(123); // Create an instance of the class
bar(my_object); // Call the function
std::cout << "In main(), value is " << my_object.get_value() << '\n';
// All done
}
And finally the second source file, e.g. bar.cpp:
#include <iostream>
#include "myheader.h"
void foo::bar(foo::my_class& val)
{
std::cout << "In foo::bar(), value is " << val.get_value() << '\n';
val.set_value(456);
}
Put all three files in the same project, and build. You should now get an executable program that outputs
In foo::bar(), value is 123
In main(), value is 456
I prefer to provide a functional interface to global data.
.h file:
extern int get_entero();
extern void set_entero(int v);
.cpp file:
static int entero = 10;
int get_entero()
{
return entero;
}
void set_entero(int v)
{
entero = v;
}
Then, everywhere else, use those functions.
#include "the_h_file"
void function()
{
cout << get_entero() << endl;
//action1...;
}
void separated_function()
{
cout << get_entero() << endl;
//action2...;
}
int main( int argc, char *argv[] )
{
function();
separated_function();
cout<< get_entero() <<endl;
//something else with the mentioned variables...;
return 0;
}
If you do not plan to modify the variable, it is generally ok to make it global. However, it is best to declare it with the const keyword to signal the compiler that it should not be modified, like so:
const int ENTERO = 10;
If you are using multiple cpp files, also consider using a header file for your structures and function declarations.
If you are planning on modifying the variable, just pass it around in function parameters.

c++ how declare function returning vector of objects

and I struggle with function which should return vector of objects but for some reason it throws errors all the time, telling that my object is undeclared identifier and vector of this objects is not valid template and points me to .h file where I declare function.
I will appropriate any explanation what that mean and how to fix this. bellow I place code from my class and starting files.
#ifndef SETUPW_H
#define SETUPW_H
#include"Square.h"
#include <iostream>
#include<string>
#include<fstream>
#include<vector>
std::vector<std::ifstream> allText();
std::ifstream loadTxt(std::string txt);
void printByLine(std::ifstream& txt);
std::vector<square> allSquares();//compiler points me to this line and that one bellow
void whichSQ(int sqNum, std::vector<square> sq);
#endif
and my class:
#ifndef SQUARE_H
#define SQUARE_H
#include"player.h"
#include"setupW.h"
#include<iostream>
#include<string>
#include<fstream>
class square
{
public:
square(std::string name, int sqNumber, std::string description, int exits, int object);
void loadSQ(std::ifstream& inFile);
void printSQ();
private:
int mSqNumber;
std::string mName;
std::string mDescription;
int mExits;
int mObject;
};
#endif
The problem arises because you have a circular dependency here. In square.cpp you firstly include square.h. But square.h contains this line #include"setupW.h" (before your class declaration). Therefor the declarations of your functions will appear before the declaration of your square class. That causes the compiler to mutter that square is not declared (at that time) when he reads std::vector<square>.
The most easiest solution would be to simply remove the include, because it is, as far as I can tell, unneccessary.

creating c++ object in c file

I have a query for creating c++ object inside c file.
I have the sample code below. When trying to import the CPlusHeader it throws an error which i could not understand.
The error is iostream' file not found as one of the error. How could i resolve this issue.
Regards,
Lenin
CPlusFile.h
include iostream
include string
using namespace std;
class CPlusFile {
int data;
public:
CPlusFile();
int getData();
};
CPlusFile.cpp
CPlusFIle::CPlusFIle() {
data = 10;
}
int CPlusFile::getData() {
return data;
}
CFile.h
int doSomething();
CFile.c
include "CFile.h"
include "CPlusFile.h"
int doSomething() {
CPlusFile object;
}
It strongly depends on what you call a "C file". Previous answer assumed that you meant a file with a .c suffix. I assume here that you mean a file that shall be compiled with a C compiler.
If my assumption is valid, then the answer is simple: You cannot instantiate C++ classes in a C file. What you can do, though, is call C++ static methods from the C code. Please refer, for example, to In C++ source, what is the effect of extern "C"? to see how to do this.
First of all, it is
#include <iostream>
#include <string>
and not
include iostream
include string
Second, if CFile.c is compiled as C, then this will not work. The C compiler will not understand the class keyword and you cannot create an instance of a class in C.
iostream is a C++ header, and isn't available if you're compiling using a C compiler. You can write C++ code in a .c file, you just need to use the right compiler.
You can use this in your C++ header file to check wether you are going to include it from C or C++ code:
#ifdef __cplusplus
The includes iostream and others, as well as using class, are only available for C++ code.
But if you want to use the CPlusFile class, which is a C++ class, you can only do that in C++ code. Best is to rename your CFile.c to CFile.cpp.
Yes, it is possible to call C++ object inside the C file. Here I performed a scenario and
it's working fine for me.
CPlusFile.h
#include<iostream>
#include<string>
using namespace std;
class cplus{
int data;
public:
cplus();
int getdata();
};
CPlusFile.cpp
#include "cplusfile.h"
cplus::cplus(){ data =10; }
int cplus::getdata(){ return data; }
CFile.h
#include "cplusfile.h"
#include<stdio.h>
int dosomething();
CFile.c
#include "cfile.h"
int dosomething(){
cplus c;
printf("%d",c.getdata());
}
int main() {
dosomething();
return 0;
}
And compile this by g++ CFile.c CPlusFile.cpp and it works fine.