How to pass vector as reference in C++? - c++

I want to pass my vector "myStaffs" from Team Class by reference to Manage Class because I want to manipulate the data of staffs and sort them. How do I pass it by reference?
Header Staff
#ifndef STAFF_H
#define STAFF_H
#include <vector>
#include <cstdlib>
#include <ctime>
#include <string>
class Staff
{
public:
Staff();
Staff(int, int, int, int);
~Staff();
static int genRanNum(int);
static Staff* createStaff(int);
const int getSize();
private:
int staSkills1,staSkills2,staSkills3;
int staId;
//int staDeptAsigned;
//std::string staName;
};
#endif
CPP Staff
#include "Staff.h"
#include <iostream>
using namespace std;
Staff::Staff():
staId(0),
staSkills1(0),
staSkills2(0),
staSkills3(0)
{
}
Staff::Staff(int id, int s1, int s2, int s3):
staId(id),
staSkills1(s1),
staSkills2(s2),
staSkills3(s3)
{
}
Staff *Staff::createStaff(int s)
{
Staff *staff = new Staff();
staff->staId = s;
staff->staSkills1 = genRanNum(10);
staff->staSkills2 = genRanNum(10);
staff->staSkills3 = genRanNum(10);
return staff;
}
int Staff::genRanNum(int num)
{
return 1+(rand()%num);
}
Staff::~Staff()
{
}
Header Team
#ifndef TEAM_H
#define TEAM_H
#include "Staff.h"
#include <vector>
#include <iostream>
using std::vector;
class Team: public Staff
{
public:
Team();
~Team();
private:
vector<Staff *> myStaffs;
};
#endif // TEAM_H
CPP Team
#include "Team.h"
const int SIZE = 30;
Team::Team():
myStaffs(SIZE)
{
for(int iStaff = 0; iStaff <= SIZE; iStaff++)
{
myStaffs[iStaff] = createStaff(iStaff);
}
}
Team::~Team()
{
}
Header Manage
#ifndef OPTIONS_H
#define OPTIONS_H
#include "Team.h"
#include <vector>
#include <iostream>
using std::vector;
class Manage
{
public:
Manage();
~Manage();
private:
// vector
};
CPP Manage
#include "Manage.h"
Manage::Manage()
{
}
Manage::~Manage()
{
}
#endif

Its simple you pass it as you would pass any other object by reference
int sortEmployee(std::vect<Staff *> &staffList> {
// ... code to sort Employee
}
and you can call it like below
vector<Staff *> myStaffs
result = sortEmployee(myStaffs);

It's as simple as
#include <vector>
void myVectorManglingFun(std::vector<Staff *> &myStaff) //notice the &
{
//do something here
}
If you don't need to modify the vector, then always use a const reference.
void myVectorReadingFun(const std::vector<Staff *> &myStaff)

Related

Undefined reference when compiling when using header and cpp file with templates in one of them

I've been trying to compile my project and I've encountered some problems when trying so. The error in particular that appears is:
[build] /usr/bin/ld: CMakeFiles/robot_control.dir/main.cpp.o:(.data.rel.ro._ZTVN4comm15cameraInterfaceE[_ZTVN4comm15cameraInterfaceE]+0x10): undefined reference to `comm::Interface<cv::Mat>::callbackMsg()'
My project is organized right now as it follows:
-${HOME_WORKSPACE}
|-main.cpp
|-src
|-communication.cpp
|-communication.hpp
The header file (communication.hpp) is:
#include <opencv2/opencv.hpp>
#include <gazebo/gazebo_client.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <algorithm>
#ifndef COMM_GUARD
#define COMM_GUARD
namespace comm
{
struct lidarMsg
{
float angle_min, angle_increment, range_min, range_max;
int nranges, nintensities;
std::vector<int> ranges;
};
template <typename T>
class Interface
{
public:
Interface() : received{false} {};
virtual void callbackMsg();
bool receptionAccomplished()
{
return this -> received;
}
T checkReceived()
{
return this -> elementReceived;
}
protected:
bool received;
T elementReceived;
};
class cameraInterface : public Interface<cv::Mat>
{
public:
void callbackMsg(ConstImageStampedPtr &msg);
};
class lidarInterface : public Interface<lidarMsg>
{
public:
void callbackMsg(ConstLaserScanStampedPtr &msg);
};
}
#endif
The source file (communication.cpp) is:
#include <opencv2/opencv.hpp>
#include <algorithm>
#include <iostream>
#include "communication.hpp"
#ifndef COMM_CPP_GUARD
#define COMM_CPP_GUARD
namespace comm
{
void cameraInterface::callbackMsg(ConstImageStampedPtr &msg)
{
std::size_t width = msg->image().width();
std::size_t height = msg->image().height();
const char *data = msg->image().data().c_str();
cv::Mat im(int(height), int(width), CV_8UC3, const_cast<char *>(data));
im = im.clone();
cv::cvtColor(im, im, cv::COLOR_RGB2BGR);
this->elementReceived = im;
received = true;
}
void lidarInterface::callbackMsg(ConstLaserScanStampedPtr &msg) {
this->elementReceived.angle_min = float(msg->scan().angle_min());
this->elementReceived.angle_increment = float(msg->scan().angle_step());
this->elementReceived.range_min = float(msg->scan().range_min());
this->elementReceived.range_max = float(msg->scan().range_max());
this->elementReceived.nranges = msg->scan().ranges_size();
this->elementReceived.nintensities = msg->scan().intensities_size();
for (int i = 0; i < this->elementReceived.nranges; i++)
{
if (this->elementReceived.ranges.size() <= i)
{
this->elementReceived.ranges.push_back(std::min(float(msg->scan().ranges(i)), this->elementReceived.range_max));
}
else
{
this->elementReceived.ranges[i] = std::min(float(msg->scan().ranges(i)), this->elementReceived.range_max);
}
}
}
}
#endif
The main file(main.cpp) includes the following header:
#include <gazebo/gazebo_client.hh>
#include <gazebo/msgs/msgs.hh>
#include <gazebo/transport/transport.hh>
#include <opencv2/opencv.hpp>
#include <opencv2/calib3d.hpp>
#include <iostream>
#include <stdlib.h>
#include "src/communication.hpp"
I included the part of the #ifndef /#define /#endif since it is a solution that I found to this kind of problem in other problem. I've been toggling the CMakeLists.txt file but still no solution that could solve this error.
You can't do this:
virtual void callbackMsg();
You have to actually provide the implementation for all template methods within the .h file.

Using custom classes in different project as member of class C++ - ERROR

I am new to C++, and I am currently working on 2 different projects within the some solution in C++ with VSC and I am encountering the error "A class-qualified name is required"; I have created a custom class in a file inside a namespace like so in project Stock:
//in file Stock.h, project Stock
#pragma once
#include "CandleStick.h"
#include "StockRecord.h"
#include "MarketQue.h"
#include <string>
#include <vector>
namespace Stock {
class Stock {
private:
std::string s_stockID;
MarketQue* s_topCur;
StockRecord s_stockRecord;
std::vector<CandleStick> s_candleSticks;
unsigned int s_totalVol;
public:
Stock(const std::string&, MarketQue&, std::vector<unsigned int>&, unsigned int); //stockID, s_topCurPrice_B, s_topCurPrice_S, s_topCurVol_B, s_topCurVol_S, cs_interval, total_vol
void updateStock(int);
~Stock();
protected:
};
}
//in file Stock.cpp, project Stock
#include "Stock.h"
Stock::Stock::Stock(const std::string& stockID, MarketQue& topPrices, std::vector<unsigned int>& csInterval, unsigned int totalVol)
:s_stockID(stockID), s_topCur(&topPrices), s_stockRecord(StockRecord(topPrices.mq_size)), s_totalVol(totalVol) {
s_candleSticks.reserve(csInterval.size());
for (unsigned int i = 0; i < csInterval.size(); i++) {
s_candleSticks.emplace_back(topPrices.mq_topPrice_S[0], topPrices.mq_topPrice_B[0], csInterval[i]);
}
};
void Stock::Stock::updateStock(int totalVol) {
s_totalVol = totalVol;
s_stockRecord.updateStockRecord(*s_topCur);
for (unsigned int i = 0; i < s_candleSticks.size(); i++) {
s_candleSticks[i].updateCandleStick((s_topCur->mq_topPrice_B)[0], (s_topCur->mq_topPrice_S)[0]);
}
}
Stock::Stock::~Stock() {};
I have successfully linked the 2 projects together (I think, tested it in the main function with a file called App.cpp in project Market):
//in file App.cpp, project Market
#include "Stock.h"
#include "MarketQue.h"
#include <string>
#include <array>
#include <vector>
int main() {
//initializing
const std::string stockID = "001";
Stock::MarketQue topPrices(3);
std::vector<float> topCurPrice_B = { 3,2,1 };
std::vector<float> topCurPrice_S = { 4,5,6 };
topPrices.mq_topPrice_B = topCurPrice_B;
topPrices.mq_topPrice_S = topCurPrice_S;
std::vector<unsigned int> topCurVol_B = { 10,11,12 };
std::vector<unsigned int> topCurVol_S = { 13,14,15 };
topPrices.mq_topVol_B = topCurVol_B;
topPrices.mq_topVol_S = topCurVol_S;
std::vector<unsigned int> cs_Interval = { 100,300,1000 };
unsigned int totalVol= 3+2+1+4+5+6;
Stock::Stock first_stock(stockID, topPrices, cs_Interval, totalVol);
totalVol = 100;
first_stock.updateStock(totalVol);
//testing update
topCurPrice_B = { 13,12,11 };
topCurPrice_S = { 14,15,16 };
topCurVol_B = { 110,111,112 };
topCurVol_S = { 113,114,115 };
topPrices.mq_topPrice_B = topCurPrice_B;
topPrices.mq_topPrice_S = topCurPrice_S;
topPrices.mq_topVol_B = topCurVol_B;
topPrices.mq_topVol_S = topCurVol_S;
}
However, when I try to use this class(Stock::Stock) as a member inside of another class (in project Market), I received the error mentioned above ("A class qualified name is required");
I first did this:
//in file Market.h, project Market
#pragma once
#include "Stock.h"
#include <string>
#include <vector>
namespace Market {
class Market {
private:
std::string marketID;
std::vector<Stock::Stock> stock; //received error
Stock::Stock stock;
public:
Market();
void updateStock();
~Market();
protected:
};
}
At this point i figured it might be because of the namespace Market making it Market::Stock::Stock and i decided to remove the namespace Market:
//in file Market.h, in project Market
#pragma once
#include "Stock.h"
#include <string>
#include <vector>
class Market {
private:
std::string marketID;
std::vector<Stock::Stock> stock;
public:
Market();
void updateStock();
~Market();
protected:
};
I'd like to ask how to fix this problem, and if possible can someone explain to me what is happenning to the code that caused the error?
Thank you very much for your time.

Why is the Default Parameter being used each time? Initializing classes

When I printed the variables passed through, the default is printed first, followed by what I want passed. So the final result remains the same. The initialization is found in Owner.h and Owner.cpp. Variables are passed starting from the Dog.cpp. I've also tried changing my print statements to Dog.owner... but the result was the same.
Owner.h
#define OWNER_H
#include <iostream>
#include <string>
#include "Dog.h"
using namespace std;
class Owner {
private:
string name;
int age;
public:
Owner(string ownerName = "Lucy" , int ownerAge = 10); // default params
string getName();
int getAge();
};
#endif
Owner.cpp
#include <iostream>
#include <string>
#include "Dog.h"
using namespace std;
// Getters
string Owner::getName() {return name;}
int Owner::getAge() {return age;}
// Constructors
Owner::Owner(string ownerName, int ownerAge) :name(ownerName), age(ownerAge) {
Owner::getName();
Owner::getAge();
}
Dog.h
#ifndef DOG_H
#define DOG_H
#include <iostream>
#include <string>
#include "Owner.h"
using namespace std;
class Dog {
private:
string breed;
int age;
Owner owner;
static int dogCount;
public:
Dog();
Dog(string, int);
// Getter and Setter methods
void setBreed(string var);
void setAge(int var);
string getBreed();
int getAge();
// Other
void printDogInfo();
static int getDogCount() {return dogCount;}
};
#endif
Dog.cpp
#include <iostream>
#include <string>
#include "Dog.h"
#include "Owner.h"
using namespace std;
// Constructors
Dog::Dog(string ownerName, int ownerAge) {
Owner(ownerName, ownerAge);
dogCount++;
}
Dog::Dog() {
}
void Dog::printDogInfo() {
cout << "owner: " << owner.getName() << ", " << owner.getAge() << " yo" << endl << endl;
}
int main() {
Dog myDog1("Belle", 15);
myDog1.setBreed("Siberian Husky");
myDog1.setAge(2);
myDog1.printDogInfo();
return 0;
}
Dog::Dog(string ownerName, int ownerAge) {
Owner(ownerName, ownerAge);
dogCount++;
}
By:
Dog::Dog(string ownerName, int ownerAge) : Owner(ownerName, ownerAge) {
dogCount++;
}
Probably, you also want to fix this:
Owner::Owner(string ownerName, int ownerAge) :name(ownerName), age(ownerAge) {
// Owner::getName(); not needed
// Owner::getAge(); not needed
}
Dog::Dog(string ownerName, int ownerAge) {
Owner(ownerName, ownerAge);
dogCount++;
}
is equivalent to
Dog::Dog(string ownerName, int ownerAge) :
breed(),
owner()
{
Owner(ownerName, ownerAge); // Create temporary
dogCount++;
}
You probably want instead:
Dog::Dog(string ownerName, int ownerAge) :
breed(),
age(0),
owner(ownerName, ownerAge)
{
dogCount++;
}

setter and getter /classes

I have a class Project and each Project can have different tasks.
Project.h:
#pragma once
#include "Task.h"
#include <vector>
using namespace std;
class Project
{
private:
vector<Task> Tasks;
public:
Project::Project(int inleesgetal);//constructor
vector<Task> GetTasks();
};
Project.cpp:
#include "Project.h"
#include <string>
#include <vector>
Project::Project(int inleesgetal)
{
//constructor
Tasks.resize(Numbertasks);
}
vector<Task> Project::GetTasks()
{
return Tasks;
}
Task.h:
#pragma once
#include <vector>
using namespace std;
class Task
{
private:
//Info:
int StartTime_Solo;
public:
Task(); //constructor
void SetStartTime_Solo(int st_s);
int GetStartTime_Solo();
};
Task.cpp:
#include "Task.h"
#include <string>
#include <vector>
#include <iostream>
using namespace std;
Task::Task()
{
//constructor
StartTime_Solo = 0;
}
int Task::GetStartTime_Solo()
{
return StartTime_Solo;
}
void Task::SetStartTime_Solo(int st_s)
{
StartTime_Solo = st_s;
}
main:
#include <iostream>
#include <vector>
#include "Task.h"
#include "Project.h"
using namespace std;
int main()
{
Project Project1(6);
Project1.GetTasks()[2].SetStartTime_Solo(55);
cout << "test:" << Project1.GetTasks()[2].GetStartTime_Solo();
return 0;
}
Now when I try to set the 3rd task of Project1 to a starttime of 55 and then print the start time out it still gives me 0 as a result.
Why is this? And how can I change my code so it actually sets the starttime to 55?
vector<Task> GetTasks();
should be
const vector<Task>& GetTasks() const;
vector<Task>& GetTasks();
And so with definitions:
vector<Task> Project::GetTasks()
{
return Tasks;
}
should be:
const vector<Task>& Project::GetTasks() const { return Tasks; }
vector<Task>& Project::GetTasks() { return Tasks; }
The problem is that you are returning a copy of the vector<Task> from the GetTasks function. You then modify this copy and throw it away right afterwards. The internal member of Project is not changed.
If you return by reference like this:
vector<Task>& GetTasks();
Then you are basically returning something that points to the internal vector, and so when you modify it, you actually modify the member data of your class.

declaring a vector as a class member

I have simple class in a header file: a.hh
#ifndef a_hh
#define a_hh
class a
{
public:
int i;
a()
{
i = 0;
}
};
#endif
Then i have a file:b.cc
#include <iostream>
#include "a.hh"
using namespace std;
int main(int argc, char** argv)
{
a obj;
obj.i = 10;
cout << obj.i << endl;
return 0;
}
>
Till this point everything is fine.
I compile the code and it compiles fine.
But as soon as i add a vector in the class:
#ifndef a_hh
#define a_hh
class a
{
public:
int i;
vector < int > x;
a()
{
i = 0;
}
};
#endif
I get a compilation error as below:
> CC b.cc
"a.hh", line 7: Error: A class template name was expected instead of vector.
1 Error(s) detected.
What is the problem with declaring a vector here as a member?
You need to #include <vector> and use the qualified name std::vector<int> x;:
#ifndef a_hh
#define a_hh
#include <vector>
class a{
public:
int i;
std::vector<int> x;
a() // or using initializer list: a() : i(0) {}
{
i=0;
}
};
#endif
Other points:
(as commented by EitanT) I removed the additional qualification a:: on the constructor
have a read of Why is "using namespace std" considered bad practice?
declaring a vector as a class member:
#include <iostream>
#include <vector>
using namespace std;
class class_object
{
public:
class_object() : vector_class_member() {};
void class_object::add_element(int a)
{
vector_class_member.push_back(a);
}
void class_object::get_element()
{
for(int x=0; x<vector_class_member.size(); x++)
{
cout<<vector_class_member[x]<<" \n";
};
cout<<" \n";
}
private:
vector<int> vector_class_member;
vector<int>::iterator Iter;
};
int main()
{
class_object class_object_instance;
class_object_instance.add_element(3);
class_object_instance.add_element(6);
class_object_instance.add_element(9);
class_object_instance.get_element();
return 0;
}
1.You need to #include <vector> and using namespace std, then a.hh just like below:
#ifndef a_hh
#define a_hh
#include <vector>
using namespace std;
class a
{
public:
int i;
vector <int> x;
a()
{
i = 0;
}
};
#endif
2. If you don't want to only use std namespace in all your code, you can specified the namespace before type, just like std::vector<int> x;