This question already has answers here:
How can I use cout << myclass
(5 answers)
Closed 6 years ago.
I don't know the term in programing of what I'm asking (this is hobby for me) and I'm trying to new things here. See my working escenario:
#include <iostream>
class Foo {
int _x;
public:
Foo () : _x(0) {}
Foo (int x) : _x(x) {}
int get () const { return _x; }
};
int main () {
Foo f1;
Foo f2(10);
std::cout << "Value: " << f1.get () << std::endl; // 0
std::cout << "Value: " << f2.get () << std::endl; // 10
return 0;
}
Is it possible to use either f1 or f2 like this:
std::cout << "Value: " << f2 << std::endl; // shows 10
updated with correct code:
#include <iostream>
class Foo {
int _x;
public:
Foo () : _x(0) {}
Foo (int x) : _x(x) {}
int get () const { return _x; }
friend std::ostream &operator<<(std::ostream &os, const Foo& f) {
return os << f.get ();
}
};
int main () {
Foo f1;
Foo f2(10);
std::cout << "Value: " << f1.get () << '\n'; // 0
std::cout << "Value: " << f2.get () << '\n'; // 10
std::cout << "Value: " << f1 << '\n'; // 0
return 0;
}
Yes, this is overloading stream insertion operator.
#include <iostream>
class Foo {
int _x;
public:
Foo () : _x(0) {}
Foo (int x) : _x(x) {}
int get () const { return _x; }
friend std::ostream& operator<< ( std::ostream& stream, const Foo& foo );
};
std::ostream& operator<< ( std::ostream& stream, const Foo& foo ) {
stream << foo._x;
return stream;
}
int main () {
Foo f1;
Foo f2(10);
std::cout << "Value: " << f1 << std::endl; // 0
std::cout << "Value: " << f2 << std::endl; // 10
return 0;
}
Related
This question already has answers here:
What is object slicing?
(18 answers)
Closed 1 year ago.
I am building up a CRTP interface and noticed some undefined behavior. So, I built up some sample code to narrow down the problem.
#include <iostream>
template <typename T>
class Base {
public:
int a() const { return static_cast<T const&>(*this).a_IMPL(); }
int b() const { return static_cast<T const&>(*this).b_IMPL(); }
int c() const { return static_cast<T const&>(*this).c_IMPL(); }
};
class A : public Base<A> {
public:
A(int a, int b, int c) : _a(a), _b(b), _c(c) {}
int a_IMPL() const { return _a; }
int b_IMPL() const { return _b; }
int c_IMPL() const { return _c; }
private:
int _a;
int _b;
int _c;
};
template <typename T>
void foo(const T& v) {
std::cout << "foo()" << std::endl;
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
std::cout << "b() = " << static_cast<Base<T>>(v).b() << std::endl;
std::cout << "c() = " << static_cast<Base<T>>(v).c() << std::endl;
}
int main() {
A v(10, 20, 30);
std::cout << "a() = " << v.a() << std::endl;
std::cout << "b() = " << v.b() << std::endl;
std::cout << "c() = " << v.c() << std::endl;
foo(v);
return 0;
}
The output of this code is:
a() = 10
b() = 20
c() = 30
foo()
a() = 134217855
b() = 0
c() = -917692416
It appears that there is some problem when casting the child class, which implements the CRTP "interface", to the interface itself. This doesn't make sense to me because the class A plainly inherits from Base so, shouldn't I be able to cast an instance of A into Base?
Thanks!
You copy and slice when you cast to Base<T>.
Cast to a const Base<T>& instead:
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
std::cout << "b() = " << static_cast<const Base<T>&>(v).b() << std::endl;
std::cout << "c() = " << static_cast<const Base<T>&>(v).c() << std::endl;
It turns out I was casting incorrectly to a value rather than a reference
std::cout << "a() = " << static_cast<Base<T>>(v).a() << std::endl;
should become
std::cout << "a() = " << static_cast<const Base<T>&>(v).a() << std::endl;
If a class has a const reference data member that happens to change outside the scope of such class, is this undefined behaviour?
As an example, let's consider the following C++ code:
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class B {
const A & a;
public:
B(const A & a) : a(a) {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
};
int main(){
A a(1);
B b(a);
std::cout << a << std::endl;
std::cout << b << std::endl;
a.change(2);
std::cout << a << std::endl;
std::cout << b << std::endl;
}
My compiler was able to execute it correctly and the debugger indicated that the x of B::a was changed.
Thank you for you help!
It is not undefined behavior. The const reference that is a member of B only means that an instance of B may not change it via that reference. Because it is a reference, however, something else may change it -- including other members of B that have their own non-const reference to the same instance of A.
Compare the addition of the member c to your existing B class, and note that we are changing it successfully within B::changeA() via the non-const reference and also from C::change() down in main():
#include <iostream>
class A {
int x;
public:
A(int x): x(x){}
void change(int y){
x = y;
}
friend std::ostream & operator << (std::ostream & os, const A & a){
os << a.x;
return os;
}
};
class C
{
A& a;
public:
C(A& a) : a{a} {}
void change(int y) { a.change(y); }
};
class B {
const A & a;
C& c;
public:
B(const A & a, C& c) : a(a), c{c} {}
friend std::ostream & operator << (std::ostream & os, const B & b){
os << b.a;
return os;
}
void changeA(int y) { c.change(y); }
};
int main(){
A a(1);
C c(a);
B b(a,c);
std::cout << a << ' ' << b << '\n';
a.change(2);
std::cout << a << ' ' << b << '\n';
b.changeA(3);
std::cout << a << ' ' << b << '\n';
c.change(4);
std::cout << a << ' ' << b << '\n';
}
See it run live on Coliru, which prints:
1 1
2 2
3 3
4 4
You may not change an object using a constant reference to it but you may change the object itself if it is not constant or using a non-constant reference to the object.
Consider the following demonstrative program.
#include <iostream>
int main()
{
int x = 10;
int &rx = x;
const int &crx = x;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
rx = 20;
std::cout << "rx = " << rx << '\n';
std::cout << "crx = " << crx << '\n';
return 0;
}
Its output is
rx = 10
crx = 10
rx = 20
crx = 20
It is the same as using a pointer to constant data. For example
#include <iostream>
int main()
{
int x = 10;
int *px = &x;
const int *cpx = &x;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
*px = 20;
std::cout << "*px = " << *px << '\n';
std::cout << "*cpx = " << *cpx << '\n';
return 0;
}
This question already has answers here:
What is a converting constructor in C++ ? What is it for?
(3 answers)
Closed 3 years ago.
I am confused how can we pass an integer when the parameter of a function only accept a class of type enemy ( void foo(const Enemy& inKlep ).
Yet when we pass to it an int (300) it compiles. Why is this?
#include <iostream>
using namespace std;
class Enemy {
public:
Enemy() { cout << "E ctor" << endl; }
Enemy(int i) { cout << "E ctor " << i << endl; }
Enemy(const Enemy& src) {cout << "E copy ctor"<< endl;}
Enemy& operator=(const Enemy& rhs) {cout<<"E="<<endl;}
virtual ~Enemy() { cout << "E dtor" << endl; }
void hornet(int i=7) const { // Not virtual!
cout << "E::hornet " << i << endl;
}
};
class Scott : public Enemy {
public:
Scott() : Enemy(1) { cout << "S ctor" << endl; }
Scott& operator=(const Scott& rhs) {cout<<"S="<<endl;}
virtual ~Scott() { cout << "S dtor" << endl; }
void hornet(int i=7) const {
cout<<"S::hornet " << i << endl;
}
};
void foo(const Enemy& inKlep) {
Enemy theEnemy;
inKlep.hornet(2);
}
int main(int argc, char** argv) {
foo(300);
cout << "Done!" << endl; // Don't forget me!
}
In C++, it is valid code for an input parameter to implicitly construct an object if the function expects an object that can be constructed from that parameter. So, for example:
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
func(5); //Valid; will print '5' to the console
}
If you don't want to allow this, you need to add the keyword explicit to the constructor to prevent this.
struct CustomInt {
int val;
CustomInt() : CustomInt(0) {}
explicit CustomInt(int value) : val(value) {}
};
void func(CustomInt obj) {
std::cout << obj.val << std::endl;
}
int main() {
//func(5); //Invalid; will cause a compile-time error
func(CustomInt(5)); //Valid; will print '5' to the console
}
I want to override parent class overloaded operators but I'd like to avoid boilerplate code rewriting all non-member operators for inherited class. Is it possible at all?
In the following example, I overloaded virtual Foo & Foo::operator+=(Foo const &) and based a free function Foo & operator+(Foo, Foo const &) out of it. In Bar, I overrode Bar & Bar::operator+=(Foo const &) override. What I want is the free function to call the overriden function when I state Bar + Foo and I expect Foo as a result. I know that overloading again Bar operator+(Bar, Foo const &) solves for that particular situation but I'd like to avoid explicitly do that if possible (think about all the other operators). And then there's also Foo + Bar that I want to return Bar.
#include <iostream>
class Foo {
public:
Foo(unsigned int bottles=11) : bottles(bottles) {} // This is odd on purpose
virtual void display(std::ostream & out) const {
out << bottles << " bottles";
}
virtual Foo & operator+=(Foo const &);
protected:
unsigned int bottles;
};
std::ostream & operator<<(std::ostream & out, Foo const & f) {
f.display(out);
return out;
}
Foo & Foo::operator+=(Foo const &f) {
bottles += f.bottles;
return *this;
}
Foo const operator+(Foo f, Foo const & g) {
return f += g;
}
class Bar : public Foo {
public:
Bar(unsigned int bottles=0) : Foo(bottles) { enforce(); }
Bar(Foo const & f) : Foo(f) { enforce(); }
void display(std::ostream & out) const override {
out << bottles << " manageable bottles";
}
Bar & operator+=(Foo const &) override;
private:
void enforce() { bottles /= 2; bottles *=2; }
};
Bar & Bar::operator+=(Foo const &f) {
Foo::operator+=(f);
enforce();
return *this;
}
int main () {
std::cout << "----- Foo + Foo -----" << std::endl;
Foo bar;
Foo becue(2);
std::cout << bar << " + " << becue << " -> (+) "
<< bar + becue << std::endl;
std::cout << "----- Bar + Bar -----" << std::endl;
Bar crazy(bar);
Bar horse(5);
std::cout << crazy << " + " << horse << " -> (+) "
<< crazy + horse << std::endl;
std::cout << "----- Bar + Foo -----" << std::endl;
std::cout << crazy << " + " << bar << " -> (+) "
<< crazy + bar << std::endl;
std::cout << "----- Foo + Bar -----" << std::endl;
std::cout << bar << " + " << horse << " -> (+) "
<< bar + horse << std::endl;
return 0;
}
I expect manageable bottles as a result each time manageable bottles are involved.
The problem derives from object slicing that occurs when invoking
Foo const operator+(Foo f, Foo const & g) {
return f += g;
}
Here, f is passed by value, which means that any additional information of subtypes of Foo are discarded. So the compiler just sees a Foo and is not able to call the polymorphic operator.
To prevent slicing you are forced to pass a pointer or a reference, but this would imply that you need an l-value as first operand and you can't use const because you are calling operator+= on it.
So you could have
Foo const operator+(Foo& f, Foo const & g) {
return f += g;
}
and it would work for your specific situation like:
Foo bar;
Bar crazy(bar);
std::cout << crazy + bar << std::endl;
Because crazy is an l-value but you won't be able to do Bar(5) + horse nor Foo(5) + horse.
This is the code.
BOOST_TYPE_ERASURE_FREE((has_arg1), arg1, 1)
namespace te = ::boost::type_erasure;
typedef te::any<
::boost::mpl::vector<
te::copy_constructible<>,
te::typeid_<>,
te::destructible<>,
te::assignable<>,
has_arg1<Vector<Val>&( te::_self& )>,
has_arg1<const Vector<Val>&( const te::_self& )>>> Bar;
struct Foo {
Vector<Val> mVals;
};
const Vector<Val>& arg1(const Foo& f) {
return f.mVals;
}
Vector<Val>& arg1(Foo& f) {
return f.mVals;
}
BOOST_AUTO_TEST_CASE(Foo1) {
Foo f;
Bar i = f;
}
It fails with the following error. Any ideas why? Is this not possible using boost type erasure. I am using Clang++ 3.5 compiler.
functions that differ only in their return type cannot be overloaded
BOOST_TYPE_ERASURE_FREE((has_arg1), arg1, 1)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
Technically, the issue is as described in Basic Usage:
If we wanted to define a const member function, we would have to change it to const _self, as shown below.
So you'd write
Live On Coliru
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/free.hpp>
#include <boost/type_erasure/member.hpp>
#include <iostream>
#include <vector>
template <typename T>
using Vector = std::vector<T>;
struct Val {};
BOOST_TYPE_ERASURE_FREE((has_free1), free1, 1)
BOOST_TYPE_ERASURE_MEMBER((has_member1), member1, 0)
namespace te = ::boost::type_erasure;
typedef te::any< ::boost::mpl::vector<te::copy_constructible<>
, te::typeid_<>
, te::destructible<>
, te::assignable<>
, has_free1<Vector<Val>&(te::_self&)>
, has_free1<Vector<Val> const&(te::_self const&)>
, has_member1<Vector<Val>&(), te::_self>
, has_member1<Vector<Val> const &(), te::_self const> >,
te::_self const &> Bar;
struct Foo {
Vector<Val> mVals;
Vector<Val>& member1() { std::cout << __PRETTY_FUNCTION__ << "\n"; return mVals; }
const Vector<Val>& member1() const { std::cout << __PRETTY_FUNCTION__ << "\n"; return mVals; }
};
Vector<Val>& free1(Foo& f) { std::cout << __PRETTY_FUNCTION__ << "\n"; return f.mVals; }
const Vector<Val>& free1(const Foo& f) { std::cout << __PRETTY_FUNCTION__ << "\n"; return f.mVals; }
int main() {
std::cout << " ==== Foo f; ==============\n";
{
Foo f {};
std::cout << "Direct: "; free1(f);
std::cout << "Direct: "; f.member1();
Bar i = f; std::cout << "\n";
std::cout << "Erased: "; free1(f);
std::cout << "Erased: "; i.member1();
}
std::cout << " ==== Foo const f; ========\n";
{
Foo const f {};
std::cout << "Direct: "; free1(f);
std::cout << "Direct: "; f.member1();
Bar i = f; std::cout << "\n";
std::cout << "Erased: "; free1(f);
std::cout << "Erased: "; i.member1();
}
}
Prints:
==== Foo f; ==============
Direct: Vector<Val>& free1(Foo&)
Direct: Vector<Val>& Foo::member1()
Erased: Vector<Val>& free1(Foo&)
Erased: Vector<Val>& Foo::member1() const
==== Foo const f; ========
Direct: Vector<Val>& free1(const Foo&)
Direct: Vector<Val>& Foo::member1() const
Erased: Vector<Val>& free1(const Foo&)
Erased: Vector<Val>& Foo::member1() const