defining constructor in a struct - c++

trying to see how structs and constructors work in header, implementation, and main files. Using constructor and default constructor. I get compilation error in mains.cpp of "undefined reference to 'numbers::numbers()'
In test.h I have:
#ifndef H_TEST
#define H_TEST
struct numbers{
int a;
int b;
numbers();
numbers(int x, int y);
};
#endif
In Numbers.cpp I have:
#include "test.h"
numbers::numbers()
{
a=0;
b=0;
}
numbers::numbers(int x, int y)
{
a=x;
b=y;
}
In mains.cpp I have:
#include<iostream>
#include "test.h"
using namespace std;
numbers num;//compilation error occurs here
int main()
{
return 0;
}

Looks like you're declaring inline constructors in the header file by putting in function bodies (albeit empty function bodies) for the constructors.
I would expect that in files that include the header, when the compiler sees the inline definitions it will use those and so never generate a symbol to be linked with the definitions in the .cpp file and therefore the definitions in the .cpp file will not be called.
Try deleting the empty function bodies in the header.

The problem is that you're default-constructing num and not reassigning it.
numbers num; // Constructs a numbers object with a = 0, b = 0 and stores it in num.
int main()
{
numbers(3,5); // Constructs a numbers object with a = 3, b = 5.
// The object is discarded after the constructor call finishes.
cout<<num.a; // Prints a from the global variable num.
return 0;
}
I think you intended to reassign num:
numbers num; // num is default-constructed to a = 0, b = 0, as before.
int main()
{
num = numbers(3,5); // num now holds a = 3, b = 5.
cout<<num.a; // Prints 3, as expected.
return 0;
}
Side notes: You generally should avoid non-const global variables. Also, when possible, initialize variables in the same line you declare them to avoid assigning the data members twice (doesn't really matter for very small objects like this one).
Edit: I didn't notice the problem that QuantumMechanic pointed out. You'll have to fix both errors for the program to work as you expect.

Related

My const pointer array only returns nullptr before main starts, which interferes with the initialization of another class

So I’m working on a project that has two const arrays of two classes (classes A and B). The class A array needs access to the class B array while initializing, but the B array always returns nullptr, which is a big problem. Perhaps it would be easier to see the code (heavily simplified because the actual classes are huge and most of the info is irrelevant here):
// A.h
#pragma once
#include <vector>
#include "B.h"
#include "B_ARRAY.h"
class A
{
private:
int bOffset; // the array offset of the corresponding element in B_ARRAY
std::vector<int> otherInfo; // other info, which determines the corresponding B_ARRAY element
public:
A(std::vector<int> i) : otherInfo(i)
{
bOffset = -1;
while (bOffset == -1)
{
// search algorithm for the corresponding element in B_ARRAY
}
}
B* getB()
{ return B_ARRAY[bOffset]; }
}
// B.h
#pragma once
#include <vector>
class B
{
private:
std::vector<int> info;
public:
B(std::vector<int> i) : info(i)
{}
std::vector<into> getInfo()
{ return info; }
}
// B_ARRAY.h
#pragma once
#include "B.h"
const int B_LENGTH = 900;
B* const B_ARRAY[B_LENGTH] =
{
new B(std::vector<int>({...})),
new B(std::vector<int>({...})),
[...]
};
// A_ARRAY.h
#pragma once
#include "A.h"
const int A_LENGTH = 1200;
A* const A_ARRAY[A_LENGTH] =
{
new A(std::vector<int>({...})),
new A(std::vector<int>({...})),
[...]
};
While it's searching in the A constructor, B_ARRAY[x] is always nullptr, which makes B_ARRAY[x]->getInfo() fail. In main(), it works just fine, so I assume this means B_ARRAY isn't fully initializing until main(). What do I have to do to make sure it fully initializes before A_ARRAY?
I could make a B object as a member of the A class, but a lot of A classes end up with identical Bs (in my current code, I'd want them to reference the same B object), and both of the actual constructor calls are already long enough as it is, so splitting them over two arrays helps keep it organized.
See, for instance, Static variables initialisation order.
"C++ guarantees that variables in a compilation unit (.cpp file) are initialised in order of declaration. For number of compilation units this rule works for each one separately (I mean static variables outside of classes). But the order of initialization of variables is undefined across different compilation units."
So you can either initialize all the static vars in one source file, or restructure the code to not depend on that order.

C++: implementing a global constant whose value is given by the user

First of all, let me say I have read similar threads on how to initialize a global variable or how to properly implement global constants. Nevertheless, these questions did not really help me with my concrete problem, as also haven't any other ressources I've consulted. The problem is the following.
I (have to) declare in a header file header.h a variable that must be constant and used by the main function in main.cpp as well as other functions defined in a another file functions.cpp (that are previously declared in header.h). The problem is this constant is a runtime constant, whose value is given by the user. How should I proceed?
I think my best shot was to do as follows. In header.h
// Header guard
namespace n
{
// Some forward declarations
extern const double mu; // The constant that should be initialized by the user.
// Some other declarations
}
then in functions.cpp
#include "header.h"
namespace n
{
// Some definitions here
double function_that_uses_mu(double a, double b)
{
// Some code using mu
return somedouble;
}
// Some other definitions
}
finally main.cpp
#include "header.h"
#include <iostream>
int main()
{
// Some code
double value_of_mu{};
std::cin >> value_of_mu;
// Validity check
extern const double n::mu{ value_of_mu };
// More code
return 0;
}
The problem is that compilation fails due to the fact that error: ‘mu’ has both ‘extern’ and initializer. However, if I tried mu = value_of_mu I would obviously get an error because I would be assigning to a const value (not initialising it). So I don't know how to proceed, or what's wrong with my code. There are two mandatory facts I must respect:
Functions/global-consts definitions, functions/global-consts declarations and main must be split in the three aforementioned files.
mu is to be defined as a constant shared by all three files.
Is this possible? How?
EDIT:
I think my problem is that an exten variable can't be initialised inside a function, but if this is so, I don't see how I do what I'm trying to.
Think about it: If a value needs to be set during the lifetime of a program, it's not really a constant. So, you shouldn't try to pretend it's a constant by declaring it as const. If you don't want the program to accidentally change its value, you have to protect it in some other way, such as making it a private member variable of a class. That way, you can restrict access to only return the value of mu as a const.
// muholder.h
class muholder
{
private:
double m_value;
public:
muholder (double ivalue): m_value(ivalue) {}
double const &value() const { return m_value; }
};
// workflow_envelope.h
class workflow_envelope
{
private:
muholder m_mu;
public:
workflow_envelope (double imu): m_mu(imu) {}
bool validity_check();
double method_that_uses_mu (double a, double b) const { return a*m_mu.value()/ b; }
void run(); // any "more code" goes in here.
};
// main
#include "workflow_envelope.h"
#include <iostream>
int main()
{
// Some code
double value_of_mu;
if (std::cin >> value_of_mu)
{
// Validity check
workflow_envelope workflow(value_of_mu);
if (workflow.validity_check())
{
workflow.run();
return 0;
}
}
return 1;
}
When you initialize a variable, you can't specify extern. This should work instead:
int main()
{
// Some code
double value_of_mu{};
std::cin >> value_of_mu;
// Validity check
using namespace n;
const double mu = value_of_mu; // no extern specifier
// More code
return 0;
}

create value in function, then save pointer on value in global pointer array

I'm relatively new to c++ and used to Java (which I like better).
I've got some pointer problem here. I created a minimal programm to simulate the behaviour of a more complex programm.
This is the code:
void test (int);
void test2(int*);
int* global [5]; //Array of int-pointer
int main(int argc, char** argv) {
int z = 3;
int y = 5;
cin >> z; // get some number
global[0] = &y; // global 0 points on y
test(z); // the corpus delicti
//just printing stuff
cout << global[0]<<endl; //target address in pointer
cout << &global[0]<<endl; //address of pointer
cout << *global[0]<<endl; //target of pointer
return 0; //whatever
}
//function doing random stuff and calling test2
void test (int b){
int i = b*b;
test2(&i);
return;
}
//test2 called by test puts the address of int i (defined in test) into global[0]
void test2(int* j){
global[0]= j;
}
The tricky part is test2. I put the address of a variable I created in test into the global pointer array. Unfortunately, this program gives me a compiler error:
main.cpp: In function 'int test(int)':
main.cpp:42:20: error: 'test2' was not declared in this scope
return test2(&i);
^
I can't find any scope problem here. I tried changing the int i of test into a global variable, but it didnt help, so I suppose, this isnt the reason.
Edit: It compiles now, but gives for cin = 20 the wrong values. *global[0] should be 400, but is 2130567168. It doesnt seem to be a int/uint problem. It is too far from 2,14e9.
Edit2: The input value doesnt matter.
'test2' was not declared in this scope It's because the compiler doesn't know what test2 is. You need to add a function prototype above the main.
void test (int b);
void test2(int& j);
or just:
void test (int);
void test2(int&);
because at this time compiler only need to know the type of the arguments and not their names.
EDIT: Moving the function definition above the main without adding the prototype will also work, but it's better to use the prototypes.
Before a function can be called, the compiler must know about it.
So you either rearrange your function definitions such that test2 comes first, test second and main last, or you put declarations of test2 and test1 before main:
void test2(int& j); // declaration
void test(int b); // declaration
int main(int argc, char** argv) {
// ...
}
void test(int b){ // definition
// ...
}
void test2(int& j) { // definition
// ...
}
This will then reveal a more serious error; you are calling test2 with an int*, but it expects an int&. You can fix this by turning the call into test2(i);.
Once your functions are neatly split into declarations and definitions, it's time to perform the next step towards the typical C++ source-file management: put the declarations into header files (usually *.h or *.hpp) and #include them from the implementation file (usually *.cpp) that contains main. Then add two more implementation files for the two function definitions. Add corresponding #includes there, too. Don't forget about include guards in the headers.
Finally, compile the three implementation files separately and use a linker to create an executable from the three resulting object files.
you need to declare test2 before you call it. Every function needs to be declared before it is called.
add these lines above main to declare the functions;
void test2(int& j);
void test2(int& j);
int main(){...}

C++ How do I to put this constructor in a cpp file?

I have a constructor in the .h file
C(std::string s = "",int i = 0,double d = 1)
{
dataMember1 = s;
dataMember2 = i;
dataMember3 = d;
}
If you provide the values of the string, int and double it will use those values, however without them, it will use the default ones. My question is how to refactor this so that I put it in a .cpp file.
When not refactoring it works fine for example if I declare
C object1("object1", 0, 1), object2; it will work, however if I refactor, the object2 will cause a compile error saying that I don't have a C() constructor
FWIW:
#include <iostream>
#include <string>
using namespace std;
class C{
public:
C(string a= "" , int foo=1, char bar=0);
};
C::C(string a, int foo, char bar){ // this can go into a .cpp file
cout<<a<<foo<<bar;
}
int main() {
C c("hi",1,'T');
return 0;
}
On IDEone .
But as others stated you should even just Google for "C++ tutorial"(actually deals with something similar in classes chapter) or read a book. It'll be a lot frustrating,faster and fulfilling...
In your header put e.g.
struct C
{
C( std::string s = "", int i = 0, double d = 1 );
};
In your implementation file, put
C::C( std::string s, int i, double d )
// Memory initializer list here, if applicable.
{
// whatever
}
Repeating the default value specifications in the implementation file, would be an error.
Remember to add the implementation file to your project, if you're using an IDE, or to compile and link it if you're working in the command line.

Trouble implementing min Heaps in C++

I'm trying to implement a minheap in C++. However the following code keeps eliciting errors such as :
heap.cpp:24:4: error: cannot convert 'complex int' to 'int' in assignment
l=2i;
^
heap.cpp:25:4: error: cannot convert 'complex int' to 'int' in assignment
r=2i+1;
^
heap.cpp: In member function 'int Heap::main()':
heap.cpp:47:16: error: no matching function for call to 'Heap::heapify(int [11], int&)'
heapify(a,i);
^
heap.cpp:47:16: note: candidate is:
heap.cpp:21:5: note: int Heap::heapify(int)
int heapify(int i) //i is the parent index, a[] is the heap array
^
heap.cpp:21:5: note: candidate expects 1 argument, 2 provided
make: * [heap] Error 1
#include <iostream>
using namespace std;
#define HEAPSIZE 10
class Heap
{
int a[HEAPSIZE+1];
Heap()
{
for (j=1;j<(HEAPISZE+1);j++)
{
cin>>a[j];
cout<<"\n";
}
}
int heapify(int i) //i is the parent index, a[] is the heap array
{
int l,r,smallest,temp;
l=2i;
r=2i+1;
if (l<11 && a[l]<a[i])
smallest=l;
else
smallest=i;
if (r<11 && a[r]<a[smallest])
smallest=r;
if (smallest != i)
{
temp = a[smallest];
a[smallest] = a[i];
a[i]=temp;
heapify(smallest);
}
}
int main()
{
int i;
for (i=1;i<=HEAPSIZE;i++)
{
heapify(a,i);
}
}
}
Ultimately, the problem with this code is that it was written by someone who skipped chapters 1, 2 and 3 of "C++ for Beginners". Lets start with some basics.
#include <iostream>
using namespace std;
#define HEAPSIZE 10
Here, we have included the C++ header for I/O (input output). A fine start. Then, we have issued a directive that says "Put everything that is in namespace std into the global namespace". This saves you some typing, but means that all of the thousands of things that were carefully compartmentalized into std:: can now conflict with names you want to use in your code. This is A Bad Thing(TM). Try to avoid doing it.
Then we went ahead and used a C-ism, a #define. There are times when you'll still need to do this in C++, but it's better to avoid it. We'll come back to this.
The next problem, at least in the code you posted, is a misunderstanding of the C++ class.
The 'C' language that C++ is based on has the concept of a struct for describing a collection of data items.
struct
{
int id;
char name[64];
double wage;
};
It's important to notice the syntax - the trailing ';'. This is because you can describe a struct and declare variables of it's type at the same time.
struct { int id; char name[64]; } earner, manager, ceo;
This declares a struct, which has no type name, and variables earner, manager and ceo of that type. The semicolon tells the compiler when we're done with this statement. Learning when you need a semicolon after a '}' takes a little while; usually you don't, but in struct/class definition you do.
C++ added lots of things to C, but one common misunderstanding is that struct and class are somehow radically different.
C++ originally extended the struct concept by allowing you to describe functions in the context of the struct and by allowing you to describe members/functions as private, protected or public, and allowing inheritance.
When you declare a struct, it defaults to public. A class is nothing more than a struct which starts out `private.
struct
{
int id;
char name[64];
double wage;
};
class
{
public:
int id;
char name[64];
double wage;
};
The resulting definitions are both identical.
Your code does not have an access specifier, so everything in your Heap class is private. The first and most problematic issue this causes is: Nobody can call ANY of your functions, because they are private, they can only be called from other class members. That includes the constructor.
class Foo { Foo () {} };
int main()
{
Foo f;
return 0;
}
The above code will fail to compile, because main is not a member of Foo and thus cannot call anything private.
This brings us to another problem. In your code, as posted, main is a member of Foo. The entry point of a C++ program is main, not Foo::main or std::main or Foo::bar::herp::main. Just, good old int main(int argc, const char* argv[]) or int main().
In C, with structs, because C doesn't have member functions, you would never be in a case where you were using struct-members directly without prefixing that with a pointer or member reference, e.g. foo.id or ptr->wage. In C++, in a member function, member variables can be referenced just like local function variables or parameters. This can lead to some confusion:
class Foo
{
int a, b;
public:
void Set(int a, int b)
{
a = a; // Erh,
b = b; // wat???
}
};
There are many ways to work around this, but one of the most common is to prefix member variables with m_.
Your code runs afoul of this, apparently the original in C passed the array to heapify, and the array was in a local variable a. When you made a into a member, leaving the variable name exactly the same allowed you not to miss the fact that you no-longer need to pass it to the object (and indeed, your heapify member function no-longer takes an array as a pointer, leading to one of your compile errors).
The next problem we encounter, not directly part of your problem yet, is your function Heap(). Firstly, it is private - you used class and haven't said public yet. But secondly, you have missed the significance of this function.
In C++ every struct/class has an implied function of the same name as the definition. For class Heap that would be Heap(). This is the 'default constructor'. This is the function that will be executed any time someone creates an instance of Heap without any parameters.
That means it's going to be invoked when the compiler creates a short-term temporary Heap, or when you create a vector of Heap()s and allocate a new temporary.
These functions have one purpose: To prepare the storage the object occupies for usage. You should try and avoid as much other work as possible until later. Using std::cin to populate members in a constructor is one of the most awful things you can do.
We now have a basis to begin to write the outer-shell of the code in a fashion that will work.
The last change is the replacement of "HEAPSIZE" with a class enum. This is part of encapsulation. You could leave HEAPSIZE as a #define but you should expose it within your class so that external code doesn't have to rely on it but can instead say things like Heap::Size or heapInstance.size() etc.
#include <iostream>
#include <cstdint> // for size_t etc
#include <array> // C++11 encapsulation for arrays.
struct Heap // Because we want to start 'public' not 'private'.
{
enum { Size = 10 };
private:
std::array<int, Size> m_array; // meaningful names ftw.
public:
Heap() // default constructor, do as little as possible.
: m_array() // says 'call m_array()s default ctor'
{}
// Function to load values from an istream into this heap.
void read(std::istream& in)
{
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
}
return in;
}
void write(std::ostream& out)
{
for (size_t i = 0; i < Size; ++i)
{
if (i > 0)
out << ','; // separator
out << m_array[i];
}
}
int heapify(size_t index)
{
// implement your code here.
}
}; // <-- important.
int main(int argc, const char* argv[])
{
Heap myHeap; // << constructed but not populated.
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
myHead.write(std::cout);
return 0;
}
Lastly, we run into a simple, fundamental problem with your code. C++ does not have implicit multiplication. 2i is the number 2 with a suffix. It is not the same as 2 * i.
int l = 2 * i;
There is also a peculiarity with your code that suggests you are mixing between 0-based and 1-based implementation. Pick one and stick with it.
--- EDIT ---
Technically, this:
myHeap.load(std::cin); // read from cin
for (size_t i = 1; i < myHeap.Size; ++i)
{
myHeap.heapify(i);
}
is poor encapsulation. I wrote it this way to draw on the original code layout, but I want to point out that one reason for separating construction and initialization is that it allows initialization to be assured that everything is ready to go.
So, it would be more correct to move the heapify calls into the load function. After all, what better time to heapify than as we add new values, keeping the list in order the entire time.
for (size_t i = 0; i < Size; ++i)
{
in >> m_array[i];
heapify(i);
}
Now you've simplified your classes api, and users don't have to be aware of the internal machinery.
Heap myHeap;
myHeap.load(std::cin);
myHeap.write(std::cout);