I'm trying to print out structs that I have made inside a function, and since these must be available outside of the function I have used pointers. I have declared the struct and functions like this in the header file:
struct Car{
double wheelDiam;
int numberOfWheels;
string brand;
};
void makeCars();
ostream & operator<<( ostream & out, const Car & elem );
void printCar( Car car);
The function that makes the cars looks like this:
void makeCars(){
Car *AstonMartin;
Car *Volvo;
Car *Audi;
Audi->numberOfWheels = 4;
Audi->wheelDiam = 20.0;
Audi->brand = "Audi";
Volvo->numberOfWheels = 4;
Volvo->wheelDiam = 23.0;
Volvo->brand = "Volvo";
AstonMartin->numberOfWheels = 5;
AstonMartin->wheelDiam = 25.0;
AstonMartin->brand = "Aston Martin";
}
and I have made another function that prints out the struct (overloaded operator=):
ostream & operator<<( ostream & out, const Car & elem ){
out << elem.brand<<" "<<elem.numberOfWheels <<" "<<elem.wheelDiam<<endl;
return out;
}
void printCar( Car car){
cout << car << endl;
}
but when I call the functions in main() it doesn't print anything and I get an error message:
int main(){
makeCars();
printCar(*AstonMartin);
return 0
}
whats the correct way to do this?
first of all, you declare the variable Car * AstonMartin in a function. This variable actually exists ONLY in the makeCars function.
you can't use your object or even delete it
a better way to do is
void setCarAttributes(Car *c)
{
// set everything for you car
c->setBrand("Aston Martin");
// etc ...
}
void printCar()
{
// print what you want
}
int main()
{
Car *AstonMartin = new Car();
setCarAttributes(AstonMartin);
printCar(AstomMartin);
}
nevermind the variable you declare in your functions can't be used in other functions. To use a variable everywhere you need to declare a global variable but in this case it's not necessary just declare a Car * and give it as parameter to your functions
Related
I want to send integer value in class to global function from main. How should I send it as a parameter,I am sending the parameters wrong
Tetris
{
private:
int num;
}
printBoard(Tetris &t);
int main()
{
Tetris tetris;
printBoard(board,tetris);
}
i want to send num , to printboard.
There are several problems with the shown code.
First, you're missing the class keyword when defining the class.
Second, the return type of the function is also missing.
Third, the function has only one parameter but you're passing two arguments.
i want to send num , to printboard
You can add a getter called getNum which you can use from inside your free function as shown below:
vvvvv------------->added this class keyword
class Tetris
{
private:
int num = 0; //don't forget to initialize
public:
//add a getter
int getNum() const
{
return num; //return a copy
}
};
vvvv----------------------->added return type as void
void printBoard(Tetris &t)
{
std::cout << t.getNum(); //use the getter
}
int main()
{
Tetris tetris;
printBoard(tetris);
}
Demo
I am trying to make a program which creates an array of pointers to objects, including inherited objects.
The error I'm getting is on the first bracket ( of the cSClass eg SArray[2] = new cSClass(...); (Last line at the bottom of all the code). The error says "no instance of constructor cSClass::cSClass matches the argument list"
Thank you
All the code is below:
The code for the header of the superclass is:
class sClass;
class sClass {
protected:
std::string name;
int yearBuilt;
public:
// Constructor
sClass(string n = "s1", int yb = 2000) {
name = n;
yearBuilt = yb;
}
// Mutator functions
void setName(string);
void setYearBuilt(int);
// Accessor functions
string getName() {
return name;
}
int getYearBuilt() {
return yearBuilt;
}
// Functions
void getInfo();
};
main class of the superclass:
#include "sClass.h"
using namespace std;
// Mutators
void sClass::setName(string n) {
name = n;
}
void sClass::setYearBuilt(int yb) {
yearBuilt = yb;
}
// Print function
void sClass::getInfo() {
cout << "Name: " << name << endl;
cout << "Year Built: " << yearBuilt << endl;
}
Code for the subclass header:
#include "sClass.h"
class cSClass : public sClass {
protected:
int maxPassengers;
public:
// Constructor
cSClass(int mp = 2000) : sClass() {
maxPassengers = mp;
}
// Mutator functions
void setMaxPassengers(int);
// Accessor functions
int getMaxPassengers() {
return maxPassengers;
}
// Functions
void getInfo() {
}
};
Code for the subclass class:
#include "cSClass.h"
// Mutators
void cSClass::setMaxPassengers(int mp) {
maxPassengers = mp;
}
// Print function
void cSClass::getInfo() {
cout << "Name: " << name << endl;
cout << "Maximum Passengers: " << maxPassengers << endl;
}
And lastly this is the main program code in which i am getting errors where i am trying to fill the array:
#include "sClass.h"
#include "cSClass.h"
int main() {
sClass *SArray[6];
SArray[0] = new sClass(...);
SArray[1] = new sClass(...);
SArray[2] = new cSClass(...);
SArray[3] = new cSClass(...);
}
Edit: Error is at the top, and the arguments I'm passing are
SArray[2] = new cSClass("RMS Queen Mary 2", 2003, 2700);
The constructor needed for this to work is missing:
SArray[2] = new cSClass("RMS Queen Mary 2", 2003, 2700);
It could look like this
class cSClass : public sClass {
cSClass(const std::string& name, int yb, int mp) :
sClass(name, yb),
maxPassengers{mp}
{}
//...
}
You also have some other problems:
You have a non-virtual destructor in the base class. When you delete your objects through a non-virtual base class pointer, only the base class destructor will be called. To fix that, add this to sClass:
virtual ~sClass() = default;
Two definitions of cSClass::getInfo(). Settle for only declaring the function in the class definition and leave the definition of the member function in the .cpp file as-is.
Memory leaks since you don't delete what you've newed. To avoid that problem, it's better to use smart pointers that will delete the object when it goes out of scope, like it will in case an exception is thrown (that you catch). Example:
#include <memory>
//...
std::unique_ptr<sClass> SArray[6]; // or std::array<std::unique_ptr<sClass>, 6> sArray;
SArray[2] = std::make_unique<sClass>();
SArray[2] = std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700);
Note: If you instead want a dynamic amount of sClass pointers, use a std::vector:
#include <vector>
//...
std::vector<std::unique_ptr<sClass>> SArray;
SArray.push_back(std::make_unique<sClass>());
SArray.push_back(std::make_unique<sClass>());
SArray.push_back(std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700));
SArray.push_back(std::make_unique<cSClass>("RMS Queen Mary 2", 2003, 2700));
There are two fundamental errors in your code!
First, you have provided two definitions for the getInfo member function of the cSClass. If you want to keep the second (out-of-body) definition, then you need to remove the definition part of the (in-body) declaration. So, replace:
// Functions
void getInfo() { /// Note: adding the { } provides a function DEFINITION
}
with this:
// Functions
void getInfo(); // No body provided, so it's JUST a declaration (defined elsewhere)
Then, the calls you make to your constructors cannot have the ... in the argument list (though I'm not sure what you are trying to achieve with this). Simply provide empty argument lists:
SArray[0] = new sClass();
SArray[1] = new sClass();
SArray[2] = new cSClass();
SArray[3] = new cSClass();
or, as there is no argument, you can invoke the 'default' constructor by omitting the argument lists completely:
SArray[0] = new sClass;
SArray[1] = new sClass;
SArray[2] = new cSClass;
SArray[3] = new cSClass;
Also, for completeness, remember to free the memory for the objects you created with new, when you're done with them:
delete SArray[0];
delete SArray[1];
delete SArray[2];
delete SArray[3];
Feel free to ask for further clarification and/or explanation.
I have class CStudent and class CStudentGroup which has one member set<CStudent>. I populate the set of an object from the class CStudentGroup. I want to iterate this set and print via the getter of the CStudent class the points of all the students in the set. I do this by assigning the set to a new one. Then I iterate the set with an iterator it. However the compiler gives an error *the object has type qualifiers that are not compatible with the member function CStudent::getP; object type is const CStudent* I would like to ask how can I do this? Thank you in advance.
#include <iostream>
#include <string>
#include <set>
using namespace std;
class CStudent {
string m_strFN;
int m_iPoints;
public:
void setP(int p) {
m_iPoints = p;
}
void setFN(string f) {
m_strFN = f;
}
int getP() {
return m_iPoints;
}
string getFN() {
return m_strFN;
}
CStudent() {
m_strFN = "123456789";
m_iPoints = 70;
}
CStudent(const CStudent& stud) {
m_strFN = stud.m_strFN;
m_iPoints = stud.m_iPoints;
};
CStudent(int p) {
m_iPoints = p;
}
};
class CStudentGroup {
set<CStudent> m_setStudents;
public:
CStudentGroup(const CStudentGroup& grp) {
m_setStudents = grp.m_setStudents;
};
CStudentGroup(set<CStudent> st) {
m_setStudents = st;
}
CStudentGroup() {
CStudent s1(50), s2, s3(s2);
m_setStudents.insert(s1);
m_setStudents.insert(s2);
m_setStudents.insert(s3);
}
set<CStudent> gets() {
return m_setStudents;
}
};
int main()
{
CStudentGroup group;
set<CStudent> stt = group.gets();
for (set<CStudent>::iterator it = stt.begin(); it != stt.end(); it++) {
cout << it->getP() << endl;
}
}
std::set stores keys as constant value, as a change of a key can be a cause of change to its position in red-black tree (typical std::set implementation).
In other words, your CStudent object are considered const or unchangeable.
It's possible to problem here using std::set::const_iterator as a type of iterator inside the loop in combination with std::set::cbegin() and std::set::cend() calls.
Another possible solution is to use foreach-loop:
for (CStudent const& student : stt)
std::cout << student.getP() << '\n';
Moreover, you would need to change CStudent::getP() declaration to be a constant method.
Objects inside a std::set are always const. That is to protect them, in case you decide you change any key field, the sorting order changes and the set invariant is broken.
So basically the set<CStudent>::iterator is a const_iterator and you get a const CStudent& reference. Since your CStudent::getP is not a const member function, you cannot use it.
Solution, make it const:
int getP() const {
return m_iPoints;
}
Naturally, you want to mark as const any function that does not change the contents of your object, not only the ones std::set requires you to do so. This is sometimes called const-correctness and is always a good practice.
Lets say I have two classes car and service. Is it possible to create the elements for both vector objects(note: I don't know if is actually refereed to as vector objects), of the car and service classes. Once both elements are created I would only like the car class constructor to be called later to have the service constructor called to get the user information?
Also if it is possible is it possible without having to change the Service constructor to a method?
using namespace std; // I know this is not the best, prof wants us to use it
class Car { Car() { //Get data from user } };
class Service { Service(){ //Get data from user } };
int main () {
int num;
vector<Car> car;
vector<Service> service;
car.push_back(Car{});
service.push_back();
for (int i = 0; i < car.size(); i++)
car[i].display(i);
cout << endl << car.size() + 1 << ". exit";
cin >> num;
service[num].Service::Service();
}
I would recommend using a std::map instead of std::vector which choice naturally follows from your task. By using it, you will be storing valid Service elements only.
map<int,Service> service;
car.push_back(Car{});
for (int i = 0; i < car.size(); i++)
car[i].display(i);
cout << endl << car.size() + 1 << ". exit";
cin >> num;
service[num]; //Service constructor will be called
I'm thinking you are looking for something like this:
class Car {
private:
std::string _make;
std::string _model;
std::string _vinNumber;
std::size_t _year;
public:
Car() : _year( 0 ) {} // default
Car( const std::string& make, const std::string& model,
const std::string& vinNumber, const std::size_t& year ) :
_make( make ), _model( model ),
_vinNumber( vinNumber ), _year( year ) {
}
void setCarInfo( const std::string& make, const std::string& model,
const std::string& vinNumber, const std::size_t& year ) {
_make = make;
_model = model;
_vinNumber = vinNumber;
_year = year;
}
std::string makeOf() const { return _make; }
std::string modelOf() const { return _model; }
std::string vinNumberOf() const { return _vinNumber; }
std::size_t yearOf() const { return _year; }
};
class Service {
private:
std::string _dealership;
std::size_t _currentMiles;
public:
Serivce() {}
std::string dealershipOf() const { return _dealership; }
std:size_t currentMilesOf() const { return _currentMiles; }
void setOrChangeDealership( const std::string& dealership ) {
_dealership = dealership;
}
void setOrChangeCurrentMiles( std::size_t miles ) {
_currentMiles = miles;
}
void setOrChangeCurrentMiles( const std::size_t& miles ) {
_currentMiles = miles;
}
};
int main() {
std::vector<Car> cars;
std::vector<Service> services;
// you can add Car to vector by either default constructor
// to be filled out later or by user defined constructor
cars.push_back( Car( "Honda", "Civic", "75273250323XMD252AG9", 2017 ) );
// or
cars.push_back( Car() );
// then you can at some point in time update elements in container
cars[i].setCarInfo( "Dodge", "Charger", "9259356M325D2680A217B", 2015 );
// As with the service class there is only a "default" constructor
services.push_back( Service() );
// Service's members will have to be updated manually and later.
return 0;
}
Regardless of what container you use, or even if you have a single instance of a class object; a CTOR for that class will be called. The only way that one will not is if either A: you declare it as protected or private in the class the prevents the class from being declared which is used with inheritance and polymorphism, or if you declare the constructor as a deleted function: SomeClass() = delete. There is no possible way to have a class instance without its constructor being called either implicitly by the compiler or explicitly by you.
Even something as simple as this:
class A {
public:
int x;
};
int main() {
A a;
a.x = 5;
return 0;
}
The line A a; behind the scenes the compiler will invoke A() on a so it would actually look like this:
A a();
Using its default constructor.
Since C++11, you have the list-initialization for vector and other containers.
http://en.cppreference.com/w/cpp/language/list_initialization
Which means, you can put an enumeration of elements in a vector while initialization.
You can use your own class constructor in it:
std::vector<Car> cars {Car(...), Car(...), Car(...)}; //C++11
Since I can't comment your question yet, is it what you expected?
I need to count the times my public member function creates new data in a loop.
Each time data is read it is saved into a private member varaible. Nothing is overwritten.
// my classType.h
const int ImpliedIndex = 1000;
class classType
{
private:
char privateMember[ImpliedIndex];
char privateMember2[ImpliedIndex];
public:
static void myMemberCounter;
void printMyInformation():
void mySupplier(const char[] );
...
};
//classType.cpp
int globalCounter = 0;
void classType::printMyInformation()
{
...
cout << privateMember << endl;
cout << globalCounter++ << endl;
}
void classType::mySupplier( const char buff[] )
{
strcpy( privateMember, buff );
}
// The main should clear things up a bit.
// main.cpp
int main()
{
while ( !inFile.eof() )
{
for ( int x = 0; x < 20; x++ )
{
// do file I/O here
// save each line of file into an temp array
// supply temp array with a routine defined in myClass
// re-use temp array until we run out of file
}
}
//close file
I need to change my 20 to a variable. Notice that in classType I used globalCounter to retrieve the number of types.
What I wanted to do is, globalCounter = memberCounter;
But I have to re-declare both of these varaibles, and I can't use myClass[ImpliedIndex].memberCounter with the assignment operator (=) or the binary insertion operator(<<).
This line:
static void myMemberCounter;
Should generate a compile-time error. It looks like a variable, but has type void, which doesn't make sense.
If you want a static ("class variable") counter, you should use a type like int. Then it would be easy for the class to use that counter to count the number of instances, by just incrementing the counter in the constructor. The count can be read by the outside world by adding a public class function to return it.