I ran this example:
#include <cstdlib>
#include <iostream>
#include <istream>
#include <ostream>
using namespace std;
class Weight {
int k;
char a[100];
public:
Weight(int kilos = 0)
:k(kilos) {}
Weight(const Weight& w)
: k(w.k) {
for(int i = 0; i < 100; ++i) this->a[i] = 'a';
cout << "WCC\n";
}
friend Weight operator+(const Weight& a, const Weight& b);
Weight& operator=(const Weight & w) {
this->k = w.k;
return *this;
}
friend ostream& operator<<(ostream&, const Weight&);
};
Weight operator+(const Weight& a, const Weight& b) {
cout << "FP\n";
int newkg = a.k + b.k;
return Weight(newkg);
}
ostream& operator<<(ostream& out, const Weight& w) {
out << w.k << " KGs";
return out;
}
class Container{
Weight w;
static Weight totalW;
static int count;
public:
Container(){++count;}
~Container(){cout << "CD\n";}
Container& add(Weight weight) {
this->w = this->w + weight;
totalW = totalW + weight;
cout << "Just added a new item that weighs " << weight << endl;
return *this;
}
static void print() {
cout << "We have " << count << " Containers with a total weight "
<< totalW << endl;
}
friend ostream& operator<<(ostream&, const Container&);
};
Weight Container::totalW;
int Container::count = 0;
ostream& operator<<(ostream& out, const Container& c){
out << "This container's " << c.w;
return out;
}
int main(int argc, char** argv) {
Container c1;
Weight *w1 = new Weight(1);
Weight *w2 = new Weight(2);
Weight *w3 = new Weight(3);
cout << "Adding items to container...\n";
c1.add(*w1).add(*w2).add(*w3);
cout << c1 << endl;
Container::print();
return 0;
}
And I got this output:
Adding items to container...
WCC
WCC
WCC
FP
FP
Just added a new item that weighs 1 KGs
FP
FP
Just added a new item that weighs 2 KGs
FP
FP
Just added a new item that weighs 3 KGs
This container's 6 KGs
We have 1 Containers with a total weight 6 KGs
CD
You can see that the copy constructor for the Weight class was called three times (Output lines 2-4) before any of the cascaded functions was called. I always thought that the left most function call will be performed before any copy constructor is called up to setup the second function call.
To be more specific, I thought this what should have happened:
WCC -> c1.add(*w1) -> WCC -> .add(*w2) -> WCC -> .add(*w3).
I thought this was necessary because the function argument will be stored in the function's stack frame. So, a stack frame needs to be setup before the copy constructor for the argument is called. Apparently, I am mistaken.
This makes me think that function arguments are store somewhere else other than the stack frame. So, where?
Do not mind the horrific coding style. This, obviously, is not meant to be in production code.
I think this is a basic compiler optimization. Since there's no requirement when a function's parameters should be initialized from supplied arguments, a compiler can do necessary optimization by rearranging them. That's why you see the copy constructors called all at once.
Related
I implemented a conversion for feet to Meters as noted below but I am unable to print out the results in my main. Below is the code generating the error in
Ftr cnum1(2);
Mtr cnum2 = cnum1.toMtr();
std::cout << cnum1.getNum() <<" feet = " << cnum2.getMtrNum() << " meters \n\n";
I’m unable to use the getNum method with cnum2 because getNum is not a method in Mtr. However the results can be accurately displayed in the Ftr.cpp file
#include "Ftr.h"
#include <iostream>
#include <string>
namespace fun::calc
{
Ftr::~Ftr() { }
Ftr::Ftr(double Ftr) noexcept { }
double Ftr::getNum() const noexcept { return m_Num;}
Mtr Ftr::toMtr() const noexcept { return Mtr(m_Num * fInMtr); }
The Ftr header file contains the following:
#ifndef __FTR_H
#define __FTR_H
#include <cstdint>
#include “Mtr.h”
namespace fun::calc
{
class Mtr;
class Ftr
{
double m_Num;
static constexpr double fInMtr = 0.3048;
public:
Ftr() = delete;
explicit Ftr(double Ftr) noexcept;
~Ftr() noexcept;
Ftr(const Ftr &other) = default;
Ftr(Ftr &&other) = default;
double getNum() const noexcept;
Ftr operator+(const Ftr &rhs) const;
Mtr toMtr() const noexcept;
};
}
#endif;
I tried to create a getMtrNum function in the Mtr.cpp as follows:
double Meters:: getMtrNum () const noexcept { return m_mtr;}
I modified main() to use getMtrNum as shown below
Ftr cnum1(2);
Mtr cnum2 = cnum1.toMtr();
std::cout << cnum1.getNum() <<" feet = " << cnum2.getMtrNum() << " meters \n\n";
The results now display 0.0 because n_mtr is initialized to 0.0 in the Mtr.h file
The output produced is :
2 feet = 0 meters
Any suggestions on how to implement this to get the correct results displayed outside of the function definition? Ideally I would like to generate the correct results without having to create getMtrNum. Please provide some guidance on the proper way to get data flowing between the 2 different classes and display the results properly.
If I understood correctly, there are two points you would like to do:
Fix the code so it shows the conversion value
Make the print without creating getMtrNum()
For the second point, if you want to keep your member private, you will need to create a getter/printer function in any case. Probably a bit more elegant if you create an ostream "<<" operator overload. In this way you don't need to use getter function during printing Meters.
Edit: To be more precise getter is still used. Once in the operator overload
std::ostream& operator<<(std::ostream& out, const Meters& m)
{
out << m.Get();
return out;
}
// in main
// std::cout << cnum1.Get() <<" feet = " << cnum2 << " meters \n\n";
A complete working example:
#include <iostream>
class Meters {
public:
Meters(const Meters& m)
:m_Meters(m.m_Meters)
{
}
Meters(double m)
:m_Meters(m)
{
}
double Get() const { return m_Meters; }
private:
double m_Meters{};
};
std::ostream& operator<<(std::ostream& out, const Meters& m)
{
out << m.Get();
return out;
}
class Feet{
public:
Feet(double f)
: m_Feet(f)
{}
static constexpr double fInMtr = 0.3048;
Feet() = default;
Meters ToMeters() const { return Meters(m_Feet * fInMtr); }
double Get() const { return m_Feet; }
private:
double m_Feet{};
};
int main()
{
Feet cnum1(2);
Meters cnum2 = cnum1.ToMeters();
std::cout << cnum1.Get() <<" feet = " << cnum2 << " meters \n\n";
}
I hope, this is what you were looking for.
I am working on an assignment for my c++ class and am having trouble with one portion of the class that requires resizing a dynamic array. For this assignment, I need to store terms of a polynomial in a dynamic array. I am specifically having trouble with the setCoefficient function of my code, where I need to resize a dynamic array if I am trying to at a term to my polynomial that is larger than what the array can currently hold.
I tried following some other stack overflow posts on how to resize a dynamic array, but keep running into errors. Currently, I am running into an error of HEAP CORRUPTION DETECTED when I try and delete the old dynamic array in the setCoefficient function.
I have commented the setCoefficient function and was hoping someone could go through and help me determine where I am going wrong. Unfortunately, I am not allowed to use the STL vector class for this assignment.
Here is my .cpp file where you can see the implementation of the setCoefficient function that I am having trouble with:
#include "poly.h"
//Default constructor. Initializes a Poly to: 0x^0
Poly::Poly()
{
cout << "No parameter constructor called" << endl;
polyArray = new int[1];
//polyArray[1] = 0;
polyArray[0] = 0;
length = 0;
}
//Constructor with one argument. Initialized to: coefficientx^0
Poly::Poly(int coefficient)
{
cout << "One parameter constructor called" << endl;
cout << "coefficient: " << coefficient << endl;
polyArray = new int[1];
//polyArray[1] = 0;
polyArray[0] = coefficient;
length = 0;
}
//Constructor with two arguments. Initialized to: coefficientx^power
Poly::Poly(int coefficient, int power)
{
cout << "Two parameter constructor called" << endl;
cout << "power: " << power << endl;
cout << "coeff: " << coefficient << endl;
polyArray = new int[power]; //I think I need to add 1 here to account for that fact that arrays start at index 0.
for (int i = 0; i < power; i++) { //I want to initialize the dynamic array to all 0's
polyArray[i] = 0;
}
polyArray[power] = coefficient;
length = power;
}
//Destructor
Poly::~Poly()
{
cout << "I am the destructor" << endl;
polyArray = NULL;
delete [] polyArray;
}
//Copy constructor. Creates a deep copy of a Poly.
Poly::Poly(const Poly& p)
{
cout << "Copy constructor" << endl;
this->length = p.length;
cout << "this->length: " << this->length << endl;
cout << "p.length: " << p.length << endl;
this->polyArray = new int[this->length];
//Loop throguh the initial Poly and assign all values in the array to the new Poly.
for (int i = 0; i<=p.length; i++) {
this->polyArray[i] = p.polyArray[i];
cout << "this polyArray: " << this->polyArray[i] << endl;
cout << "p.polyArray: " << p.polyArray[i] << endl;
}
}
void Poly::setCoefficient(const int coefficient, const int power) {
if (power > this->length) {
//we need to resize the array we currently have.
//Here I am creating a new array that will temporarily store larger values
int* resizedArray = new int[power * 2];
//This for loop assigns all the values in the current object's array to the new array (resizedArray)
for (int i = 0; i < this->length; i++) {
resizedArray[i] = this->polyArray[i];
}
//Here I am adding the term that we wanted to add in the first place with setCoefficient
resizedArray[power] = coefficient;
//Deleting the terms in polyArray
delete [] this->polyArray;
//Creating a new array that has been resized
this->polyArray = new int[power * 2];
//Setting the values of the temporary array, resizedArray, to the array of the current object.
this->polyArray = resizedArray;
//modifying the length of the current object.
this->length = power * 2;
}
else {
this->polyArray[power] = coefficient;
}
}
and for completeness, here is my .h file as well (although I dont think the issue is in my .h:
// ------------------------------------------------ Poly.h ----------------------------------------------
#ifndef Poly_H
#define Poly_H
#include <iostream>
#include <string>
using namespace std;
class Poly {
friend ostream& operator<<(ostream& out, const Poly& p);
friend istream& operator>>(istream& in, Poly& p);
public:
//Member functions
Poly(); //Default constructor. Initializes a Poly to: 0x^0
Poly(int coefficient); //Constructor with one argument. Initialized to: coefficientx^0
Poly(int coefficient, int power); //Constructor with two arguments. Initialized to: coefficientx^power
Poly(const Poly& p); //Copy constructor. Creates a deep copy of a Poly.
~Poly(); //Destructor
int degree() const; //Returns the largest degree term in a Poly.
double getCoefficient(const int power) const; //returns the coefficient of the x^power term.
//Poly setCoefficient(const int coefficient, const int power); //Sets the coefficient of the term indicated by the power.
void setCoefficient(const int coefficient, const int power);
// Arithmetic operators
Poly operator+(const Poly& p) const;
Poly operator-(const Poly& p) const;
// Boolean comparison operators
bool operator==(const Poly& p) const;
bool operator!=(const Poly& p) const;
// Assignment operators
Poly& operator=(const Poly& p);
Poly& operator+=(const Poly& p);
Poly& operator-=(const Poly& p);
Poly& operator*=(const Poly& p);
//Clean up/delete all Poly terms.
void clear();
//Checks if the Poly is empty or not.
bool isEmpty() const;
private:
int length; //# of terms in the Poly/size of the array
int* polyArray;
};
#endif
One error is here (cout statements removed for brevity):
this->length = p.length;
this->polyArray = new int[this->length];
for (int i = 0; i<=p.length; i++) {
this->polyArray[i] = p.polyArray[i];
}
The test in your for-loop should be i<p.length rather than i<=p.length. Otherwise you are writing one value past the end of polyArray, which invokes undefined behavior (which can result and often does in a crash)
So I'm trying to write a vector class which can take objects without a default constructor. To do so I'm using an array of raw pointers. Thing is, when I'm instantiating a new vector, let's call it 2, based upon a previous vector, let's call it 1-- it points to the underlying address of said previous object, 1. So when I insert a new value into 1, 2 is updated as well.
#ifndef MYVECTOR_MYVECTOR_H
#define MYVECTOR_MYVECTOR_H
#include <sstream>
#include <stdexcept>
#include <memory>
#include <vector>
#include <ostream>
template<typename T>
class MyVector;
template<typename T>
std::ostream& operator<<(std::ostream& out, const MyVector<T>& myVec){
out << "{";
for(int i = 0; i < myVec.numElem; i++){
out << &myVec.elements[i] << " ";
}
out << "}";
return out;
}
template<typename T>
class MyVector{
public:
int numElem;
int capacity;
T** elements;
MyVector(const unsigned int& numElements, const T& value) : numElem(numElements), capacity(numElements * 2){
elements = new T*[capacity];
for(int i = 0; i < numElem; i++){
elements[i] = new T(value);
}
}
template<typename U>
MyVector(const std::vector<U>& values): numElem(values.size()), capacity(values.size() * 2){
elements = new T*[capacity];
for(int i = 0; i < numElem; i++){
elements[i] = new T(values[i]);
}
}
void insert(const unsigned& pos, const T& value){
elements[numElem] = new T(*elements[numElem - 1]);
numElem++;
for(unsigned int i = numElem - 1; i > pos; i--){
elements[i] = elements[i - 1];
}
elements[pos] = new T(value);
}
};
#endif
Per comment #1:
class NoDefault {
public:
NoDefault(const int& value) : value(value) {}
int value;
};
std::ostream& operator<<(std::ostream& out, const NoDefault& noDefault) {
out << noDefault.value;
return out;
}
int main() {
MyVector<NoDefault> noDefaultVec(std::vector<NoDefault>{7,8,9,10,11});
MyVector<MyVector<NoDefault>> vecvec(2, noDefaultVec);
std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
std::cout << "vecvec = " << vecvec << std::endl;
noDefaultVec.insert(3, 99);
vecvec.insert(1, noDefaultVec);
std::cout << "noDefaultVec = " << noDefaultVec << std::endl;
std::cout << "vecvec = " << vecvec << std::endl;
return 0;
}
You perform a shallow copy instead of a deep copy.
A shallow copy of your vector creates a new collection which shares elements with an old one. What follows, any change made to the original object will cause a change in a new one. What you need in that case is a deep copy, which duplicates every element from the source to the destination. After performing such a copy you are left with two vectors with seperate set of data.
Providing a copy constructor for your class solves the problem, but you should also remember about implementing destructor and assignment operator, basing on The Rule Of Three. You can also consider adding move constructor and move assignment operator (or one assignment operator following copy-and-swap idiom).
EDIT: need to delete post -- problem was trivial (typographical error) and won't be of any help to others
I'm getting errorLNK2019, the unresolved external error, when trying to use an operator overload in one of my cpp files. I've looked all over, and many people have been able to fix the problem by making sure to define every single method in their class prototypes.
I think this has to do a lot with my project design to be honest, but I really can't pinpoint exactly why this error is happening
Here's the code:
//a.cpp
//
// ... skipped all code to bottom to where i modified it
//OVERLOADED FUNCTIONS
int operator+(const int n, const a& entry){
return n + entry.getTime();
}
ostream& operator<<(ostream & out, const a& entry){
out << entry.getTitle() << " by " << entry.getArtist()
<< " (" << entry.getTime() << ") ";
return out;
}
//*********************************************************
// a.h
//... only posting what I changed
//
// Inside the class..
class a
{
public:
friend ostream& operator<<(const ostream& out, const a& entry);
friend int operator+(const int n, const a& entry);
//..
//.. SNIPPED
//..
}
I run into the error when I try to output a b object in the show() method.
//b.cpp
#include "b.h"
b b::etnsl(const int &indexOfItemToAdd) const{
if (originalObjects != NULL && indexOfItemToAdd >= (*originalObjects).size()){
throw "Index out of bounds";
}
b x(originalObjects);
vector<int> *iCopy = x.getIndices();
(*iCopy) = indices;
iCopy->push_back(indexOfItemToAdd);
x.setSum(sum + (*originalObjects)[indexOfItemToAdd].getTime());
return x;
}
void b::show() const{
cout << " Item at loc " << "0x" << this << ":" << endl;
//int j = indices.size();
//if (j == 0)
if (size == 0)
cout << " Empty item." << endl;
else{
for (int i = 0; i < size; i++) //ERROR IN LOOP
cout << " Index " << indices[i] << " : " << (*originalObjects)[indices[i]] << endl;
}
}
int b::getSum() const{
return sum;
}
void b::setSum(const int& num){
sum = num;
}
vector<int>* b::getIndices(){
return &indices;
}
//*********************************************************
//b header class
#ifndef B_H
#define B_H
#include <iostream>
#include <vector>
#include "a.h"
using namespace std;
class b{
private:
int sum, size;
vector <a> *originalObjects;
vector <int> indices;
public:
b(vector<a> *orig = NULL) //counts as 2 constructors: default and a custom one.
: sum(0), originalObjects(orig), size(indices.size()) {
}
b etnsl(const int &indexOfItemToAdd) const;
void show() const;
int getSum() const;
void setSum(const int& num);
vector<int> *getIndices();
};
#endif
ostream& operator<<(ostream & out, const iTunesEntry& tune)
is not same as
ostream& operator<<(const ostream& out, const iTunesEntry& entry);
// ~~~~~
inside the iTunesEntry class (friend method)
And const shouldn't be used as you will have to modify the out object of ostream
I have a very silly problem that I just can't figure out. I'm trying to overload the << operator in my "PrioQueue" class. I'm still pretty new to C++ and i've tried almost every example I could find on the web but nothing works.
The PrioQueue is a template class I made that works like a normal Queue but puts the highest value it receives on the top.
PrioQueue<int> intq1(5);
intq1.push(1);
intq1.push(2);
intq1.push(1);
cout << intq1;
The << operator should write all the values that I've pushed to the queue with a '|' in between. So like this:
2 | 1 | 1 |
This is my overload operator << method.
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out.write(q.pop()); //This method pops off the top value and returns it
}
return out;
}
I hope this is enough information but if not. This is my full code:
#include "stdafx.h"
#include <iostream>
#include <ostream>
using namespace std;
template <typename Type>
class PrioQueue
{
private:
Type *bottom_;
Type *top_;
int size_;
public:
PrioQueue(Type size){
bottom_ = new Type[size];
top_ = bottom_;
size_ = size;
}
friend PrioQueue operator+(PrioQueue q1, PrioQueue q2){
while(!q2.empty()){
q1.push(q2.pop());
}
return q1;
}
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out.write(q.pop());
}
return out;
}
//Checks to see if the given value is bigger than the bottom character.
//If so, the bottom and the given value swap places.
//If not, the value gets placed at the top of the queue
void push(Type t){
if(*bottom_ < t){
*top_ = *bottom_;
*bottom_ = t;
}else{
*top_ = t;
}
top_++;
}
int num_items() {
return (top_ - bottom_);
}
Type pop(){
return *(bottom_++);
}
int full() {
return (num_items() >= size_);
}
int empty() {
return (num_items() <= 0);
}
void print(){
cout << "Queue currently holds " << num_items() << " items: " ;
for (Type *element=top_-1; element >= bottom_; element--) {
cout << " " << *element;
}
cout << "\n";
}
int getSize(){
return size_;
}
~PrioQueue(){ // stacks when exiting functions
bottom_ = 0;
delete[] bottom_;
}
};
void intExample(){
PrioQueue<int> intq1(5);
intq1.push(1);
intq1.push(2);
intq1.push(1);
cout << intq1;
intq1.print();
PrioQueue<int> intq2(5);
intq2.push(8);
intq2.push(2);
intq2.push(5);
intq2.print();
PrioQueue<int> intq3(10);
intq3 = intq1 + intq2;
intq3.print();
cout << intq3;
}
void charExample(){
PrioQueue<char> charq1(5);
charq1.push('t');
charq1.push('h');
charq1.push('g');
charq1.print();
PrioQueue<char> charq2(5);
charq2.push('i');
charq2.push('q');
charq2.push('k');
charq2.print();
PrioQueue<char> charq3(10);
charq3 = charq1 + charq2;
charq3.print();
}
int main(){
intExample();
charExample();
return 0;
}
This would work:
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out << q.pop() << "|";
}
return out << "\n"; // if you want a newline, otherwise just "return out;"
}
Edit Note that for this to work, you will have to modify your queue to be copyable. You need to add a copy constructor and an assignment operator (see the rule of three) or use a type that is copyable and assignable to store your data (see std::vector, std::deque, or container adapter std::priority_queue if this is not an exercise).
The problem is that the out.write() expects a const char* and size. First of all, your Type will not implicitly convert to const char* and also, you're missing an argument.
Using out << q.pop() will fix the problem for you.