Why is it giving me an undefined reference to MySet::MySet() while trying to print my vector? Any help would be much appreciated. Thanks
#include <iostream>
#include <vector>
using namespace std;
class MySet{
public:
MySet();
MySet(const vector<int> v3);
void printVector(const vector<int>& newMyVector);
};
int main()
{
vector<int> myVector;
myVector.push_back(1);
myVector.push_back(2);
MySet m;
m.printVector(myVector);
return 0;
}
void MySet::printVector(const vector<int>& newMyVector){
cout << "Vector: ";
for(unsigned int i = 0; i < newMyVector.size(); i++)
{
cout << newMyVector[i] << "|";
}
}
Why is it giving me an undefined reference to MySet::MySet() while trying to print my vector?
You are creating an instance of MySet using
MySet m;
That uses the default constructor. The default constructor has been declared in the class but it has not been defined. You can fix it by defining it.
MySet::MySet() {}
Your program does not include a definition for the constructor of MySet. The constructor's name is MySet::MySet(). So when you try to create an instance of the object, the compiler does not know what to do. There are a couple solutions:
Remove the line right after "public:" that declares the constructor. If you don't declare any constructors, your object will just use a default constructor supplied by the compiler which might be good enough.
Or, add a definition for the constructor somewhere in your program.
Or, you can change the line that declares MySet::MySet() so that it also defines it.
The code for option 2 would look like this, somewhere outside the class:
MySet::MySet()
{
// do stuff here to construct object
}
The code for option 3 would look like this, somewhere inside the class:
MySet()
{
// do stuff here to construct object
}
Related
This question already has answers here:
What is The Rule of Three?
(8 answers)
Closed 4 years ago.
Take the following example:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
class Foo{
public:
Foo(){
cout << "Constructing the default way..." << endl;
this->num = (int*)malloc(sizeof(int));
}
Foo(int a){
cout << "Using a custom constructor..." << endl;
this->num = (int*)malloc(sizeof(int) * a);
}
~Foo(){
cout << "Destructing..." << endl;
free((void*)num);
}
int* num;
};
int main()
{
vector<Foo> objects(5);
for(Foo& v : objects) printf("%x0x\n", v.num);
cout << "\n---------------\n";
cout << "END OF PROGRAM!\n";
cout << "---------------\n\n";
return 0;
}
Creating the vector by passing it an initial count of objects creates every single object individually, hence, all of them have their num at different addresses and their destructors are called at the end of the program.
However, if I want to create the vector by giving it a custom constructor like vector<Foo> objects(5, Foo(5)); (This is only my guess) a temporary object is constructed and then copied to every object in the array. Effectively, this makes every single object in the vector have their num pointer point to the same memory. Plus that memory gets freed when the initialization is finished and then every single object becomes useless.
How do I go around this without making the custom constructor into a new Init(int) function and running it on every single object in the vector? (Of course changing malloc into realloc).
You could solve your problem with a vector of unique_ptr's to the Foo objects.
class Foo
{
public:
Foo(int i) {}
// ...
};
#include <algorithm>
#include <vector>
auto main() -> int
{
std::vector<std::unique_ptr<Foo>> foos(100);
std::generate(foos.begin(), foos.end(), []() { return std::make_unique<Foo>(5); });
}
However, you don't want to do this because otherwise you would have to go the extra indirection with the unique_ptr when calling anything on a vector's Foo object.
As others have already suggested, you should store Foo's int members in a vector. Then you can just reserve the space in the vector and emplace_back (construct) your Foo objects directly in the vector of Foo's.
#include <vector>
class Foo
{
public:
Foo() {}
Foo(int i) : ints(i) {}
private:
std::vector<int> ints;
};
namespace
{
constexpr auto NumberOfFoos = 100;
}
auto main() -> int
{
std::vector<Foo> foos;
foos.reserve(NumberOfFoos);
for (auto i = 0; i < NumberOfFoos; ++i) {
foos.emplace_back(10);
}
}
Regarding your code, you might want to have a look at these additional sources and answers (as already suggested by other comments):
Rule of three
Stop using std::endl
Why is “using namespace std” considered bad practice?
Two problems preventing a solution.
1) You need to implement your custom copy and assignment operators to do the deep copying since the default shallow copy (as you point out) doesn't do the right thing.
2) You need to let the object remember how large an array you are allocating for the copy/assignment implementations to work.
I am having a problem with assigning new values to a dynamic int array that is a data member variable of the class IntersectionFlowRate(). I can initialize and print the values of the array inside the constructor. However, when I exit the constructor to the another class and then later call a function within the IntersectionFlowRate() class passing in variables to overwrite the initial values of the data member it will segmentation fault. I have debugged to find that overwriting the array is causing the seg fault. And that even attempting to access the dynamic array within one of its functions will seg fault.
My question is how can I edit the values of a dynamic int array member variable from within one of its functions i.e setArrayElement(int index, int x).
Here is some of my code. Sorry if I am unclear or missing something ridiculous. I have been stuck on this for hours.
#ifndef INTERSECTIONFLOWRATE_H
#define INTERSECTIONFLOWRATE_H
class IntersectionFlowRate
{
public:
IntersectionFlowRate();
~IntersectionFlowRate();
void setFlowCycle(int index, int flow);
private:
int* m_flowRateMotorCycle;
};
#endif
in the .h file ^
#include "IntersectionFlowRate.h"
#include <cstdlib>
#include <iostream>
#include <new>
using namespace std;
IntersectionFlowRate::IntersectionFlowRate()
{
const int SIZE = 4; //Constant for m_flowRates[] size
//DYNAMIC MEMORY DELETE LATER
m_flowRateMotorCycle = new int[SIZE];
for(int i = 0; i < SIZE; i++){
m_flowRateMotorCycle[i] = 0;
cout << m_flowRateMotorCycle[i] << endl;
cout << "WE GOT HERE" << endl;
}
}
void IntersectionFlowRate::setFlowCycle(int index, int flow){
cout << "INDEX: " << index << endl;
cout << "FLOW: " << flow << endl;
m_flowRateMotorCycle[index] = flow; //seg fault is here
}
I have another class that creates a pointer to a IntersectionFlowRate() object and then calls its setFlowCycle function passing in two VALID ints. With the debugging I was able pass 0 and 3 to the function setFlowCycle(0, 3) just fine and output those variables within the function.
#ifndef TRAFFICSIM_H
#define TRAFFICSIM_H
#include "IntersectionFlowRate.h"
using namespace std;
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
~TrafficSim(); //Destructor
private:
IntersectionFlowRate* m_flowRate;
};
#endif
#include "TrafficSim.h"
#include "IntersectionFlowRate.h"
#include <iostream>
#include <string>
#include <fstream>
#include <cstdlib>
using namespace std;
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
I replicated the error with this code. If no one else can I am completely unsure of what is possibly wrong anymore.
You are setting a local variable called m_flowRate, not the member variable m_flowRate of your TrafficSim class:
Instead of this:
TrafficSim::TrafficSim()
{
IntersectionFlowRate* m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
It should be this:
TrafficSim::TrafficSim()
{
m_flowRate = new IntersectionFlowRate();
m_flowRate->setFlowCycle(0, 3);
}
But overall, it not need be a pointer. It could be an object member within your class. That would cut down on the pointer usage a bit:
class TrafficSim
{
public:
TrafficSim(); //Default Constructor
TrafficSim(const char* file); //Constructor
private:
IntersectionFlowRate m_flowRate;
};
Then:
TrafficSim::TrafficSim()
{
m_flowRate.setFlowCycle(0, 3);
}
As to your question as to how to incorporate usage of std::vector in your class, here is a code sample of the IntersectionFlowRate class, rewritten using vector:
Vector sample
Also, another source of problems is that your classes fail to follow the Rule of 3 when you have pointers to dynamically allocated memory in your class.
Using std::vector takes care of this automatically, but if you insist on using pointers, you need to adhere to the directions at the link posted.
Yes, use a std::vector, it is much simpler, and it is a template so it also pretty fast and works any type (best for primitive types or pointers to objects) , and it also has boundary checking and other useful things.
If you need fast array-like access then you could use std::map which associates a key with a value, like so
std::map<UINT, YourClass*> m_mapIDs_to_YourClass;
When you first start using stl containers they might seem a little strange, but after a short while you cannot do without them, luckily they have been part of the C++ standard for some time now.
Boundary check for both these containers can be done by comparing your iterator to mapYourMap.end(), if they are equal you have passed the last element and trying to access data through the iterator will cause an exception.
Example for std::vector (if vecInt is a vector< int >):
vector<int>::iterator it = vecInt.begind();
if (it == vecInt.end()) return; // vector is empty
do { // runs through elememts until out of bound, useful for searching
i++
while (it != vecInt.end());
I have inherited my class from std::vector. Now I want to overload the []-operator.
When I try to assign a new value to my vector, e.g. v[0]=5, I should receive the message OK.
This is my code (I know, that makes no sense, I'm just playing around):
#include<vector>
#include<iostream>
class Vec : public std::vector<int> {
public:
int operator[](int);
};
int Vec::operator[](int i) {
(*this)[i] = i;
std::cout << "OK";
return 123;
}
int main() {
Vec v;
v[0]=5;
}
Unfortunately I get the following error:
In member function ‘int Vec::operator[](int)’:
error: lvalue required as left operand of assignmen
In function ‘int main()’:
error: lvalue required as left operand of assignment
This particular error is caused because you are not returning an lvalue, generally defined as something that can appear to the left of an assignment, such as v[0] = 5;. You have more problems as pointed out in the other answers but this is the specific issue you face with that error message (a).
The correct specification for overloading the index operator is:
int& operator[] (const int nIndex);
You have to return a reference to the item (so it can be modified) if you want to treat it as an lvalue. The following code shows a fix, although obviously all array indexes map to the same value in this simplified case:
#include <vector>
#include <iostream>
class Vec : public std::vector<int> {
public:
int& operator[] (int); // <-- note the '&'
private:
int xyzzy;
};
int& Vec::operator[] (int idx) { // <-- note the '&'
std::cout << "OK\n";
return xyzzy;
}
int main () {
Vec v;
v[0] = 5;
v[1] = 6;
std::cout << v[22] << '\n';
return 0;
}
The output of this is:
OK
OK
OK
6
In reality, you wouldn't map all indexes to the same value, the code above is simply to illustrate the correct function signature. I haven't bothered to give a more complete example since subclassing classes with non-virtual destructors regularly leads to problems in non-trivial code (b).
(a) It's not usually considered a good idea to subclass std::vector since the destructor isn't virtual, so you can get into trouble when trying to destroy an object polymorphically.
You're probably better off using a has-a relationship (where your class contains a vector) rather than an is-a relationship (where you inherit).
That unfortunately means you may have to create a lot of pass-through methods from your class to the underlying vector (although only the ones you need) but it will solve the problem with the destructor.
(b) See (a) :-)
You'd need to return a reference to your element - however note that even if you did, you'd run into inifinite recursion - your operator[] calls itself.
Either way - inheriting from std::vector isn't a good idea. Use composition instead.
The code below illustrates how to call the operator[] from the vector base class....
#include <iostream>
#include <vector>
struct Vec : std::vector<int>
{
int& operator[](int n)
{
std::cout << "operator[](" << n << ")\n";
return std::vector<int>::operator[](n);
}
};
int main()
{
Vec v;
v.push_back(10);
v.push_back(20);
v[0] += 5;
std::cout << v[0] << ' ' << v[1] << '\n';
}
Output when I run it:
operator[](0)
operator[](1)
operator[](0)
15 20
Don't take all this talk about "do not inherit from std::vector" too seriously: you have to go out of your way to delete a dynamically allocated Vec using a std::vector<int>*, or do an accidental by-value slicing copy - and even then it'd probably only bite you if you had added data members. You should make sure you understand those risks then make your own assessment, but for small utility programs etc. it's productive to inherit from such classes sometimes....
I have a class that holds a vector, which also inherits another class:
class txtExt : public extention
{
private:
string openedFile_;
public:
vector<string> txtVector; //the vector i want to call
};
I fill the vector in a method within a class:
class Manager : public extention
{
// there is some other code here that I know does work
// and it calls this function:
void organizeExtention(string filename, string ext)
{
if(ext == "txt")
{
txtExt txtExt;
txtExt.txtVector.pushback(filename);
}
}
}
and this is my main class where i attempt to call the vector:
int main()
{
// some code here that does previous operations like getting the path
// and filling the vector
// I've tried many ways of trying to call the vector
// here is an example of one:
vector<txtExt*> testVector;
for(int i = 0; i < testVector.size(); ++i)
{
cout << testVector[i] << endl;
}
return 0;
}
I have a few questions:
Am I calling the vector wrong?
Is my vector empty?
Do I have to make my vector global, so other classes can see it?
Note: I've been able to print out the vector where I load the vector using a very simple for loop
Well, as has been said you have a few errors in the code posted, and you maybe have some misunderstandings as well. But to answer the question asked, this
testVector[i]->txtVector
is the way to access the txtVector object that is inside each of your txtExt objects.
If that doesn't work for you then it's because one of the other errors/misunderstandings you have in your code.
To summarize:
reread the first chapters of a good C++ book ( The Definitive C++ Book Guide and List ), then try try to fix your program and deal with each error one at the time.
There are several errors in your code.
First of all, there's no operator << for printing entities of the type txtExt*.
Even object of type txtExt is not printable just like that.
In addition, the testVector you made is empty, so no .size() will be zero, and there's going to be no looping.
Are you really sure that you like to inherit both your classes from 'extension' ?
You can't call a vector, you can access it.
Having a data member (like the vector) public is not a good idea.
Calling a variable by the same name as a class is a very bad idea.
I have trouble guessing what your code should do. Here's a simple example of things you need to understand:
#include <iostream>
#include <vector>
#include <string>
class TxtExt
{
public:
std::vector<std::string> txtVector;
};
int main(){
TxtExt oneTxtExt;
oneTxtExt.txtVector.push_back("hello");
oneTxtExt.txtVector.push_back("world");
for( auto &i : oneTxtExt.txtVector ){
std::cout << i <<std::endl;
}
}
The following code is correct, but has absolutely no effect. You could as well just write {}:
{
TxtExt TxtExt;
TxtExt.txtVector.pushback(filename);
}
You here create a new object, push back to it (btw it is called push_back), but then the object is destroyed at the end of the scope. Also, don't name you objects the same as the class, it becomes really confusing.
I can't figure out why I get this error: "the function was not declared". I am still a newbie at programming, but I am trying my best to learn it!
so here is my code, I would be realy greatful if you could help me:
main:
#include <iostream>
#include <vector>
#include "szovegkezelo.h"
using namespace std;
int main()
{
string sz;
beolvas(sz);
kiir(sz);
return 0;
}
header:
#ifndef SZOVEGKEZELO_H_INCLUDED
#define SZOVEGKEZELO_H_INCLUDED
#include <iostream>
using namespace std;
class szovegkezelo {
protected:
string sz;
public:szovegkezelo
void beolvas(string &sz);
void kiir(string t);
};
#endif // SZOVEGKEZELO_H_INCLUDED
cpp:
#include "szovegkezelo.h"
#include <iostream>
void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
From what it looks like, you are trying to call a classes function (method) called 'beolvas' from 'main' but because it belongs to a class, you can't call it like that, you need to create an instance of that class and call the method on that instance, or make the function static and call it from the class.
Your first option is to create an instance of the class and then call the methods on the class like so:
int main()
{
string sz;
szovegkezelo szov;
szov.beolvas(sz);
svoz.kiir(sz);
return 0;
}
Your second option is to make the functions in your class static, this way they will not need an instance of the class to be called:
int main()
{
string sz;
szov::beolvas(sz);
svoz::kiir(sz);
return 0;
}
static void szovegkezelo::beolvas(string &sz)
{
getline(cin, sz);
}
static void szovegkezelo::kiir(string t)
{
cout << "a beadott szoveg: " << t << endl;
cout << "a string hossza: " << t.size() << endl;
}
Been a while since I've done anything static in c++ so please correct me if I've done something wrong in the second option.
Your two or more data types... error comes from a misuse of...something...after that public access specifier.
Change this:
public:szovegkezelo
to this:
public:
If you're trying to make a constructor, it needs to be declared like any other function, minus the return type.
Your other error occurs because this function was declared improperly.
Other than that, you need to create an object before you can call the class's functions. Each object has it's own set of variables that the functions work on. I would seriously recommend reading a good beginner C++ OOP book.
Somewhere in main, you need to create an object:
szovegkezelo myObject;
Then, use it to call functions:
myObject.kiir (sz);
Finally, note that your data members should typically be declared with the private access specifier. protected has nothing to do with normal classes that are not inherited from.
couple of things :
1) In main you have not instantiated an object of szovegkezelo and you are trying to call beolvas . Compiler is looking for a free function beolvas whereas you have declared beolvas as member function
2) public:szovegkezelo is not right if you are looking for a default constrcutor that does nothing don't have that line else if you need to do something specific with default construct declare it as szovegkezelo() in header.
3) as mentioned in comments it is not a good practice to put
using namespace std in header files or any using namespace