I'm working on a simple progress indicator class, and I have a question about using a std::ostream object as a class member. The following example compiles and runs correctly on OS X and Linux.
#include <iostream>
#include <string>
struct ProgressIndicator {
public:
ProgressIndicator(unsigned int update_interval, std::string message,
std::ostream& outstream = std::cerr)
: update_interval(update_interval), message(message),
stream(outstream.rdbuf()), _counter(0), _interval(update_interval)
{
}
void increment(unsigned int by = 1)
{
_counter += by;
if(_counter >= _interval) {
stream << message << _counter << std::endl;
_interval += update_interval;
}
}
unsigned int get_count()
{
return _counter;
}
protected:
unsigned int update_interval;
std::string message;
std::ostream stream;
private:
unsigned long _counter;
unsigned long _interval;
};
int main()
{
ProgressIndicator p1(5, "progress <stdout> ", std::cout);
for(int i = 0; i < 15; i++) {
p1.increment();
}
ProgressIndicator p2(5, "progress <stderr> ", std::cerr);
for(int i = 0; i < 15; i++) {
p2.increment();
}
return 0;
}
I understand that std::ostream objects cannot be copied, and must be passed by reference. But I don't understand why initializing with stream(outstream) doesn't work, and why I had to resort to the rdbuf() hack. Is there no "better", more idiomatic way to do this?
You are still copying the std::ostream. Even though the constructor isn't copying the parameter, it still needs to copy the object into ProgressIndicator::stream somehow.
One way to solve your problem would be to store a reference to the stream, though this only works if you know the stream object will outlast your class instance:
struct ProgressIndicator {
ProgressIndicator(std::ostream& outstream = std::cerr /* ... */)
: stream(outstream) /* ... */ {}
// ...
protected:
std::ostream& stream;
// ...
};
Related
In the code bellow, instead of using new function "void print()", how can I use the overloaded "<<" operator in order to print the required information?
Or to be exact, where is the mistake here?
Overloaded << operator in one of the inherited classes:
friend ostream &operator<<(ostream &os, DigitSecret &s){
for(int i=0;i<s.n;i++)
os<<s.digits[i];
return os<<" Simple entropy: "<<s.simpleEntropy()<<" Total: "<<s.total();
}
void printAll (Secret ** secrets, int n) {
for(int i=0;i<n;i++){
cout<<secret[i] //This is printing an address, however that is not what i want.
secrets[i]->print(); //I want that to work like this.
}
}
The whole code: https://pastebin.com/MDCsqUxJ
I want line 134 and 143 to work correctly.
EDIT:
secret[i] is of type Secret*, you should derefence first and then your overload will get picked:
cout << *secret[i];
Side note: use std::vector instead of raw dynamic allocation.
See this snippet:
class base {
public:
virtual void print() = 0;
virtual std::ostringstream get_value() const = 0;
int get_id() const { return id_; }
protected:
int id_;
};
class A:public base {
public:
A(std::string val):val_(val){ id_ = 1; }
void print() override { std::cout << " I am A" << std::endl; }
std::ostringstream get_value() const { std::ostringstream ss; ss << val_; return ss; }
private:
std::string val_;
};
class B :public base {
public:
B(int val):val_(val) { id_ = 2; }
void print() override { std::cout << " I am B" << std::endl; }
virtual std::ostringstream get_value() const { std::ostringstream ss; ss << val_; return ss; }
private:
int val_;
};
std::ostream& operator << (std::ostream& os, const base* p)
{
std::string str;
if (p->get_id() == 1) {
str = ((A*)(p))->get_value().str();
os << "A " << str << "\n";
}
else
if (p->get_id() == 2) {
str = ((B*)(p))->get_value().str();
os << "B " << str << "\n";
}
return os;
}
void PrintAll(base** a)
{
for (int i = 0; i<2; i++)
std::cout << a[i];
}
int main()
{
base* a[2];
a[0] = new A("Hello");
a[1] = new B(10);
PrintAll(a);
return 0;
}
Output:
I Solved it this way:
void printAll (Secret ** secrets, int n) {
for(int i=0;i<n;i++){
DigitSecret* ds = NULL;
CharSecret* cs = NULL;
ds = dynamic_cast<DigitSecret*>(secrets[i]);
cs = dynamic_cast<CharSecret*>(secrets[i]);
if(ds!=NULL)
cout<<*ds<<endl;
else
cout<<*cs<<endl;
// secrets[i]->print();
}
}
Basically in this case, I have to use dynamic_cast with new pointer from the derived class, on each pointer from the array, and check if the pointer is !=NULL, and then use the overloaded operator on the dereferenced new pointer.
Say I have a simple vector class, vec:
#include <iostream>
#include <stdlib.h>
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
double & operator[](int i) const {
check_index(i);
return data[i];
}
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
Now suppose I have a special type of vector with sparse structure, e.g., where every even-index is zero. Call this oddvec. Instances of oddvec should be declared just as with the vec class, but underneath, the memory use should be efficient since only half the data is non-zero.
The accessor for the oddvec class should return 0 if the index is even, and return the odd-index element (stored sequentially) otherwise. There a couple problems with this:
The double & return type is violated if the index is even, since the constant value, 0, is returned.
It's not clear to me how to handle the situation when an even index element is used as an lvalue. E.g., v[0] = 3.0 should not be allowed in the oddvec class, but is perfectly acceptable in the vector class. We can't simply throw an error when even indexes are used, because even indexes are fine as long as the intention is as an rvalue.
How do I design the accessor function for the oddvec class, while both keeping the memory storage efficient and inheriting all the methods from the parent?
Non-working example of oddvec:
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor (doesn't work!)
double & operator[](int i) const {
check_index(i);
if (i%2 == 0)
return 0;
else
return data[(i-1)/2];
}
};
Upon compilation:
main.cpp: In member function ‘double& oddvec::operator[](int) const’:
main.cpp:49:20: error: invalid initialization of non-const reference of type ‘double&’ from an rvalue of type ‘double’
return 0;
Working example using proxy classes:
I have implemented a proxy class as suggested in the answer below.
proxies.h
#ifndef PROXIES_H
#define PROXIES_H
#include <iostream>
#include <stdlib.h>
class proxy {
public:
proxy(int i, double v, double * d) {
index = i;
value = v;
data = d;
}
void operator=(double rhs) {
data[index] = rhs;
}
friend std::ostream & operator<<(std::ostream & outs, const proxy & p) {
outs << p.value;
return outs;
}
protected:
int index;
double value;
double * data;
};
class oddproxy : public proxy {
public:
oddproxy(int i, int v, double * d) : proxy(i, v, d) {}
void operator=(double rhs) {
if (index%2 == 0) {
std::cerr << "Even entries of oddvec are not assignable.\n";
exit(1);
}
data[index/2] = rhs;
}
};
#endif
vectors.h
#ifndef VECTORS_H
#define VECTORS_H
#include "proxies.h"
class vec {
public:
vec() {}
// Constructor.
vec(int n) {
len = n;
data = new double[len];
}
// Destructor.
~vec() { delete [] data; }
// Accessor.
proxy operator[](int i) const {
check_index(i);
return proxy(i, data[i], data);
}
inline int length() const { return len; }
// Other methods...
// ....
protected:
int len;
double * data;
void check_index(int i) const {
if(i < 0 || i >= len) {
std::cerr << "Bad access.\n";
exit(1);
}
}
};
class oddvec : public vec {
public:
// Constructor.
oddvec(int n) {
len = n;
data = new double[len/2];
}
// Accessor.
oddproxy operator[](int i) const {
check_index(i);
return oddproxy(i, (i%2 == 0) ? 0 : data[i/2], data);
}
};
#endif
main.cpp
#include <iostream>
#include "vectors.h"
int main () {
int N = 5;
vec V(N);
oddvec O(N);
for(int i=0; i < V.length(); i++) {
V[i] = i;
if(i%2 != 0) {
O[i] = i;
}
}
for(int i=0; i < O.length(); i++) {
std::cout << "V[" << i << "]=" << V[i] << ", "
<< "O[" << i << "]=" << O[i] << "\n";
}
O[0] = 13;
return 0;
}
output
V[0]=0, O[0]=0
V[1]=1, O[1]=1
V[2]=2, O[2]=0
V[3]=3, O[3]=3
V[4]=4, O[4]=0
Even entries of oddvec are not assignable.
You can use proxy object to do this.
simple sample code:
#include <iostream>
#include <vector>
using namespace std;
class very_odd_vector{
public:
class only_odd_proxy;
friend class only_odd_proxy;
only_odd_proxy operator [](int index);
int operator [](int index)const{return index%2==0?0:content[index/2];}
unsigned int size()const{return content.size()*2;}
private:
vector<int> content{1,3,5,7,9};
};
class very_odd_vector::only_odd_proxy{
public:
only_odd_proxy(very_odd_vector& vec,int index):vec(vec),index(index){}
operator int(){return index%2==0 ? 0 : vec.content[index/2];}
only_odd_proxy& operator =(int value){
if(index%2==0)
cout << "BAD OPERATION";//any error you want
else
vec.content[index/2] = value;
return *this;
}
private:
very_odd_vector& vec;
int index;
};
auto very_odd_vector::operator [](int index)->only_odd_proxy{return only_odd_proxy(*this,index);}
int main(){
very_odd_vector v;
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
cout << "writting value\n";
for(int i=0;i<v.size();++i){
cout << i << ':';
v[i]=10;
cout << '\n';
}
cout << "reading value\n";
for(int i=0;i<v.size();++i)
cout << v[i] <<'\n';
}
Edit for updated part of question :
I think this class will fit your need more.
//Both base and inherit class return this class
class maybe_readonly_proxy {
public:
maybe_readonly_proxy(double* data, bool readonly):readonly(readonly),data(data){}
maybe_readonly_proxy& operator=(double rhs) {
if(readonly){/*whatever error*/}
else {*data = rhs;}
return *this;
}
operator double()const{return *data;}
private:
bool readonly;
double * data;
};
You may need a variable to contain readonly (0 in this case) value, or modify the operator double() the check readonly state
Or just implement get and set method separately and do not use this proxy may be another choice.
so basically I have some c++ code in VS2013 that looks like this
#include "stdafx.h"
#include <malloc.h>
#include <stdio.h>
class Test_Class {
public:
Test_Class() {
printf("In Test_Class()\n");
allocated_array = (int*)malloc(sizeof(int) * 64);
printf("Allocated %p\n", allocated_array);
}
~Test_Class() {
printf("In ~Test_Class()\n");
printf("Freeing %p\n", allocated_array);
free(allocated_array);
printf("Freed %p\n", allocated_array);
}
private:
int* allocated_array;
};
class Holder {
public:
Holder() {
printf("In Holder()\n");
m_test_class = Test_Class();
}
~Holder() {
printf("In ~Holder()\n");
}
private:
Test_Class m_test_class;
};
class Game {
public:
Game() {
printf("In Game()\n");
m_holder = Holder();
}
~Game() {
printf("In ~Game()");
}
private:
Holder m_holder;
};
int main()
{
printf("In main()\n");
Game game = Game();
return 0;
}
That when ran, gives me this output:
What I'm wondering is, why is the destructor of the same Test_Class object getting called twice before it crashes (due to trying to free the same pointer twice). I went through with the debugger, to make sure it wasn't just a new instance of the class that had been given the same pointer as the other object, and sure enough it was the exact same object.
I understand that since the Test_Class object is a member of Holder, that it would create a Test_Class object, then create another one and destroy the old one (which it seems to do), but this weird behaviour of calling the destructor on the same seems to occur when I make a member of type Holder in the Game class. Obviously there's something I'm missing.
The reason is, that your compiler is not able to eliminate the copy assignment Game game = Game();.
The correct code would be Game game;.
What your code does is to construct an object as rvalue, assign it to a new object game that is a lvalue. So in this line Game game = Game(); two objects are constructed and one of them is immediately destructed after assignment.
Edit:
The same holds for m_Holder and so on - of course.
You might benefit from instrumenting your class to see what's happening. A technique I often use is to create a specific instrumentation class with static counters for each significant event. Here's an example that is little more than a wrapper around a numeric type (specifically double in this case), but it illustrates the idea:
class Goofy
{
private:
double num;
public:
Goofy(double n = 0) : num(n) { ++constructions; }
Goofy(const Goofy &g2) : num(g2.num) { ++copyconstructions; }
Goofy(const Goofy &&g2) : num(g2.num) { ++moves; }
~Goofy() { ++destructions; }
Goofy &operator=(const Goofy &g2) { num = g2.num; return *this; }
Goofy &operator-=(const Goofy &g2) { num -= g2.num; return *this; }
Goofy &operator+=(const Goofy &g2) { num += g2.num; return *this; }
// none of the code below is needed by the new version of the function
Goofy &operator*=(const Goofy &g2) { num *= g2.num; return *this; }
friend std::ostream &operator<<(std::ostream &out, const Goofy &g2) {
return out << g2.num;
}
static void report(int line) {
std::cout << "At line " << line
<< "\nconstructions = " << Goofy::constructions
<< "\n copies = " << Goofy::copyconstructions
<< "\n moves = " << Goofy::moves
<< "\n destructions = " << Goofy::destructions
<< "\n existing = " << Goofy::constructions +
Goofy::copyconstructions + Goofy::moves -
Goofy::destructions
<< '\n';
}
static long constructions;
static long copyconstructions;
static long moves;
static long destructions;
};
long Goofy::constructions = 0;
long Goofy::copyconstructions = 0;
long Goofy::moves = 0;
long Goofy::destructions = 0;
Here's an example of how it was used: https://codereview.stackexchange.com/questions/56532/kahan-summation/56592#56592
There's a lot wrong with your code, but I'm going to go with it anyways. You need to (at a minimum) implement the copy constructor and copy assignment operator. I would use new, delete and swap since this is C++ and not C. Something like this:
Test_Class() {
allocated_array = new int[64];
}
~Test_Class() {
delete[] allocated_array;
}
Test_Class(const Test_Class& rhs)
{
allocated_array = new int[64];
std::copy(&rhs.allocated_array[0], &rhs.allocated_array[0] + 64, &allocated_array[0]);
}
Test_Class& operator=(const Test_Class rhs)
{
if (this != &rhs)
{
Test_Class(rhs).swap(*this);
}
return *this;
}
void swap(Test_Class & s) throw()
{
std::swap(this->allocated_array, s.allocated_array);
}
I'm using something like the following. Is there a better way?
for (int i = 0; i < sizeof(Person) ; i++) {
const char &cr = *((char*)personPtr + i);
cout << bitset<CHAR_BIT>(cr);
}
I would suggest to provide a serialize_as_binary utility in your Person class.
template<typename T>
void serialize_as_bin(const T &t, ostream& os) {
const unsigned char *p = reinterpret_cast<const unsigned char *>(&t);
for(size_t s = 0; s < sizeof t; ++s, ++p) serialize_as_bin(*p, os);
}
template<>
void serialize_as_bin(const unsigned char &t, ostream& os) {
// Code to serialize one byte
std::bitset<CHAR_BIT> x(t);
os << x;
}
struct Person {
A a;
B b;
ostream& serialize_as_binary(ostream& os) {
serialize_as_bin(a, os);
serialize_as_bin(b, os);
return os;
}
void deserialize_from_binary() {
// Similar stuff if required
...
}
};
Live example here
Disclaimer: This is meant as a simple non-serious solution that doesn't care about padding. Prints the bytes and bits from right to left.
template<typename T>
void PrintBits(const T& o) {
for (size_t i = sizeof(o) - 1; i < sizeof(o); --i)
std::cout << std::bitset<CHAR_BIT>(reinterpret_cast<const unsigned char*>(&o)[i]);
}
Hey i'm new to c++ and still working out its perticularities. I'm having the darnedest time trying to figure out whats going wrong with this code. I've stepped through it and everything is calculating correctly. The issue is that value_array in the base class doesn't seem to be retaining the values once the derived class Calculate function ends. I think i've declared and allocated the array properly. I'm stumped...
#include <iostream>
class Indicator
{
protected:
double * value_array;
double * input_array;
int input_size;
public:
Indicator(double input[], int size)
{
input_array = input;
input_size = size;
value_array = new double[size]; // issue with value_array
}
double operator[] (int index) { return value_array[index]; }
void virtual Calculate() {}
~Indicator() { delete[] value_array; }
};
class SMA : public Indicator
{
private:
int nperiod;
double sum;
public:
SMA(double input[], int size, int period) : Indicator(input, size)
{
nperiod = period;
sum = 0;
Calculate();
}
void Calculate();
};
void SMA::Calculate()
{
for (int i=0; i<input_size; i++)
{
if (i > nperiod - 1)
{
sum += input_array[i] - input_array[i-nperiod];
value_array[i] = sum / nperiod;
}
else
{
sum += input_array[i];
value_array[i] = sum / (i+1);
}
}
}
int main(int argc, const char *argv[]) {
double input[] = {1,2,3,4,5,6,7,8,9,10};
Indicator indicator = SMA(input,10,5);
double value = indicator[0];
std::cout << "value: " << value << std::endl;
std::cin.get();
exit(0);
}
Update:
Here is the code implemented with vectors. I wanted to leave the input as double[] to be consistent with other libraries, any other potential issues I should be aware of?
#include <iostream>
#include <vector>
class Indicator
{
protected:
std::vector<double> value_vector;
double * input_array;
int input_size;
public:
Indicator(double input[], int size)
{
input_array = input;
input_size = size;
value_vector.reserve(size);
}
double operator[] (int index) { return value_vector[index]; }
void virtual Calculate() {}
};
class SMA : public Indicator
{
private:
int nperiod;
double sum;
public:
SMA(double input[], int size, int period) : Indicator(input, size)
{
nperiod = period;
sum = 0;
Calculate();
}
void Calculate();
};
void SMA::Calculate()
{
for (int i=0; i<input_size; i++)
{
if (i > nperiod - 1)
{
sum += input_array[i] - input_array[i-nperiod];
value_vector.push_back(sum / nperiod);
}
else
{
sum += input_array[i];
value_vector.push_back(sum / (i+1));
}
std::cout << "sma: " << value_vector[i] << std::endl;
}
}
int main(int argc, const char *argv[]) {
double input[] = {1,2,3,4,5,6,7,8,9,10};
Indicator indicator = SMA(input,10,5);
for (int i=0; i<10; i++)
{
std::cout << "main: " << indicator[i] << std::endl;
}
std::cin.get();
exit(0);
}
That's because you're violating the Rule of Three. Since your class manages a resource, it needs a copy constructor and an assignment operator. I strongly suggest replacing any T* data member with a std::vector<T> data member. Then you don't need to write those special member functions manually.
Hia,
a few things are wrong.
As FredOverflow says you need a copy constructor and assignment, something like:
Indicator::Indicator(const Indicator& other)
{
input_size = other.input_size;
//direct copy of reference as indicator doesn't own this data
//Note a shared pointer (such as boost::shared_ptr) would be better than a naked reference
input_array = other.input_array;
//construct a new set of data
value_array = new double[input_size];
//do you want to copy the data too? maybe a memcpy follows?
memcpy(value_array, other.value_array, input_size*sizeof(double));
}
Then you need an assignment
Indicator&
Indicator::operator=(const Indicator& other)
{
//make sure you are not assigning itself
if(this != &other)
{
input_size = other.input_size;
//direct copy of reference as indicator doesn't own this data
//Note a shared pointer (such as boost::shared_ptr) would be better than a naked reference
input_array = other.input_array;
//destroy old data and construct a new set of data
delete[] value_array;
value_array = new double[input_size];
//do you want to copy the data too? maybe a memcpy follows?
memcpy(value_array, other.value_array, input_size*sizeof(double));
}
return *this;
}
You probably also want to make the destructor virtual - see here for why -
it helps prevent memory leaks in the destructor of SMA
virtual ~Indicator() { delete[] value_array; }
Use std::vector instead of raw arrays.
std::vector handles all the memory management and copying and so forth.
Cheers & hth.,