Can someone please explain why i->value() and (i + 1)->value() prints 1 and 3 not 1 and 4 like x[0]->value() << x[1]->value()
#include <iostream>
#include <vector>
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int value() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int value() const { return m_n + 1; }
};
int main()
{
const A a(1); //a.m_n=1
const B b(3); //b.m_n=3
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y;
y.push_back(a);
y.push_back(b);
V::const_iterator i = y.begin();
std::cout << x[0]->value() << x[1]->value()
<< i->value() << (i + 1)->value() << std::endl;
return 0;
}
Thank you
y.push_back(b); creates an instance of A which is a copy of the A subobject in b, and pushes that onto the vector. There are no instances of B on the vector, nor could there be, so B::value() is not called. Read about object slicing
void push_back (const value_type& val);
will create an A copy of val if the vector is defined as std::vector<A> V.
You see here so called slicing problem.
This is why you should use
std::vector<A*> V
or
std::vector<shared_ptr<A> > V
Related
I want to move the data of a virtual base class object before it is cleared, but I don't know how. Can anyone help?
I prefer not to copy because it is used in a program that cares about performance.
#include <iostream>
#include <vector>
class A {
public:
void clear() {
handleClear();
}
virtual int size() = 0;
protected:
virtual void handleClear() = 0;
};
class B : public A {
public:
int size() override {
return buffer_.size();
}
void handleClear() override {
buffer_.clear();
}
std::vector<int> buffer_;
};
void write(A& a) {
std::cout << a.size() << std::endl;
// How can I move out the data before a.clear() called.
// A new_a = std::move(a);
std::cout << a.size() << std::endl;
a.clear();
}
int main()
{
B b;
b.buffer_ = {1, 2};
write(b);
}
I'm trying to populate a vector of type pointer to class B, which I'll be using later.
When I try to read the vector's element, the value I'm getting is different from what I've given.
Can someone please help me here, what mistake I'm making and how to correct it?
Thanks
#include <iostream>
#include <vector>
class B {
public:
int b;
B (int n) {
b = n;
}
};
std::vector<B*> v;
class A {
public:
int a;
void func(int n);
};
void A::func(int n) {
B obj_b(n);
B* ptr = &obj_b;
v.push_back(ptr);
}
int main() {
A obj_a;
obj_a.a = 5;
obj_a.func(4);
std::cout<<obj_a.a<<std::endl;
for (auto it:v) {
std::cout<<it->b<<std::endl;
}
}
The output I'm getting is:
5,
32765
Whereas the expected output is:
5,
4
Using value instead of pointer, as per the comments above:
#include <iostream>
#include <vector>
class B {
public:
int b;
B (int n) {
b = n;
}
};
std::vector<B> v;
class A {
public:
int a;
void func(int n);
};
void A::func(int n) {
v.emplace_back(n);
}
int main() {
A obj_a;
obj_a.a = 5;
obj_a.func(4);
std::cout<<obj_a.a<<std::endl;
for (auto& e:v) {
std::cout<<e.b<<std::endl;
}
}
You can use heap allocations and take advantage of std::unique_ptr<T>. Here is the fix:
#include <iostream>
#include <vector>
#include <memory>
class B
{
public:
B ( const int n )
{
b = n;
}
int b;
};
std::vector< std::unique_ptr<B> > v; // use a vector of B pointers
// ( std::unique_ptr<B> )
class A
{
public:
void func( const int n );
int a;
};
void A::func( const int n )
{
v.push_back( std::make_unique<B>( n ) ); // returns a pointer object of type
} // std::unique_ptr<B>
int main ()
{
A obj_a;
obj_a.a = 5;
obj_a.func( 4 );
std::cout << obj_a.a << std::endl;
for ( const auto& ptrB : v )
{
std::cout << ptrB->b << std::endl; // use -> operator to have access to
} // ptrB's members
return 0;
}
Hopefully, this helps.
I am working with conversion operators and I an error just popped out of nowhere. C class is derived from B and has no relation with class A, however, debugger shows that when doing C* val1 = new C val1 is showed as C* {A<B>}. It also produces an error because that A in the C* pointer has a size of an unreasonable size (it gives a different size each time it is executed so I just suppose it gets a number from another application).
#include <iostream>
#include <vector>
template<typename widget_type>
class A
{
public:
std::vector<widget_type*> value;
virtual ~A() {}
void Add(widget_type* val)
{
value.push_back(val);
}
template<typename return_type>
operator A<return_type>()
{
unsigned int size = this->value.size();
std::vector<return_type*> return_value;
return_value.reserve(size);
for (unsigned int i = 0; i < size; i++)
{
return_value[i] = dynamic_cast<return_type*>(this->value[i]);
}
A<return_type> target;
target.value = return_value;
return target;
}
};
class B
{
public:
virtual ~B() {}
};
class C : public B
{
public:
void Print()
{
std::cout << "C CALL\n";
}
};
class D : public B
{
};
int main()
{
std::cout << "Start!\n";
A<C> source;
C* val1 = new C;
source.Add(val1);
A<B> target = source;
A<B>* target2 = dynamic_cast<A<B>*>(&source);
std::cout << "END\n";
}```
for (unsigned int i = 0; i < size; i++)
{
return_value[i] = dynamic_cast<return_type*>(this->value[i]);
}
You are invoking undefined behaviour by accessing return_value[i] on an empty vector.
Let's say we have the following scenario:
We have a base abstract class A. Then we have classes B and C which derived from A. We also have class D which is a custom implementation of a std::vector<T> - it contains a private property list of type std::vector<T> and some custom methods to work with it.
Now my problem is as follows: I would like to overload the operator + in class A to be able to do this:
B* b = new B();
C* c = new C();
D mList = b+c; //the property *list* of mList would contain b an c
I have tried everything and can't seem to be able to get it to work and am out of ideas. Is it even possible to override an operator in a base abstract class so that it will apply to derived classes?
EDIT:
Here is what I have tried so far:
File A.h:
#pragma once
#include <string>
#include <iostream>
using namespace std;
class A
{
protected:
double price;
string name;
public:
A() :name(""){};
A(string n, double p){
price = p;
name = n;
};
~A(){};
virtual void calculate(double value) = 0;
virtual void print() const = 0;
};
File B.h:
#pragma once
#include "A.h"
class B : public A
{
private:
public:
B() :A(){};
B(string n, double p) :A(n,p){};
~B();
void calculate(double value)
{
price = price + value;
}
void print() const
{
cout << name << " says: " << " " << price;
}
};
File C.h:
#include "A.h"
class C : public A
{
private:
public:
C() :A(){};
C(string n, double p) : A(n,p){};
~C();
void calculate(double value)
{
price = price * value;
}
void print() const
{
cout << name << " says: " << " " << price;
}
};
File D.H:
#include <vector>
class D
{
private:
vector<A*> list;
public:
D(){}
~D()
{
int len = list.size();
for (int i = 0; i < len; i++)
{
delete list[i];
}
};
void push(A* item)
{
list.push_back(item);
}
A* pop()
{
A* last = list.back();
list.pop_back();
return last;
}
//I have tried overriding it here and in A.h
friend D D::operator+(A* first, A* second)
{
D temp;
temp.push(first);
temp.push(second);
return temp;
}
};
It looks like you're are adding two pointers, so A::operator+() won't even be called. But to answer your question, yes, operator overloading is inheritable. Even from an abstract base class.
class A
{
public:
virtual void test() = 0;
int operator+(const A &a) {return 42;}
};
class B : public A
{
void test() {};
};
class C : public A
{
void test() {};
};
int main()
{
B* b = new B();
C* c = new C();
cout << "result: " << *b + *c << endl;
return 0;
}
Output:
result: 42
When c in C* and d is a D* if you write c+d you're just adding pointers, whatever overloads you defined.
Maybe you could redefine pointer addition for A* with a global operator(A*, A*) (not sure it's possible) but it would be quite dangerous for users since it overrides standard behavior.
The better solution is to define operators on references (const) and not pointers, which in your case is a little less convenient since you'd have to write: list = *c + *d;
Also, since you're using containers of pointers for polymorphism, I strongly recommend using shared_ptr.
Working code below (simplified, but with the ability to add more than 2 elements):
#include <list>
using std::list;
struct A {
list<const A*> operator+(const A& right) { // A + A
list<const A*> r;
r.push_back(this);
r.push_back(&right);
return r;
}
list<const A*> operator+(const list<const A*> & right) { // A + list
list<const A*> r = right;
r.push_front(this);
return r;
}
virtual void print() const = 0;
};
list<const A*> operator+(const list<const A*> & left, const A & right) { // list + A
list<const A*> r = left;
r.push_back(&right);
return r;
}
#include <iostream>
struct B : A {
void print() const { std::cout << "B" << std::endl; }
};
struct C : A {
void print() const { std::cout << "C" << std::endl; }
};
int main() {
B b;
C c;
B* pb = new B;
list<const A*> lst = b + c + *pb;
for(list<const A*>::iterator i = lst.begin(); i != lst.end(); ++i) {
(*i)->print();
}
return 0;
}
Take a look at this code-example:
#include <iostream>
class B;
class A;
class A
{
public:
virtual void overrideProp() = 0;
friend int operator+(const B& b, const A& a);
friend std::ostream& operator<<(std::ostream& os, const A& a)
{
return os << a.prop;
}
protected:
int prop;
};
class B : public A
{
public:
B(){overrideProp();}
void overrideProp(){prop=1;}
};
class C : public A
{
public:
C(){overrideProp();}
void overrideProp(){prop=3;}
};
int operator+(const B& b, const A& a)
{
return b.prop + a.prop;
}
class D
{
public:
void operator=(const int& i){d = i;}
friend std::ostream& operator<<(std::ostream& os, const D& a)
{
return os << a.d;
}
private:
int d;
};
int main()
{
B b;
C c;
D d; d = b+c;
std::cout << "B contains: " << b << " C contains: " << c << " D contains: " << d;
}
The output is B contains: 1 C contains: 3 D contains: 4
Here's an compilable and runnable example (http://codepad.org/cQU2VHMp) I wrote before you clarified the question, maybe it helps. The idea is that the addition overload can either be unary (and D defined as a friend), as here, or defined as a non-member binary operator using public methods. Note that I have to dereference the pointers b and c to make this work, as adding pointers often don't make sense.
#include <iostream>
#include <string>
class D {
public:
void Foo() {
std::cout << "D: " << member_ << std::endl;
}
friend class A;
private:
std::string member_;
};
class A {
public:
virtual void Foo() = 0;
A(const std::string &member) : member_(member) {}
D operator+(const A &rhs) {
D out;
out.member_ = member_ + " " + rhs.member_;
return out; // Uses the default copy constructor of D
}
protected:
std::string member_;
};
class B : public A {
public:
B(const std::string &member) : A(member) {}
void Foo() {
std::cout << "B: " << member_ << std::endl;
}
};
class C : public A {
public:
C(const std::string &member) : A(member) {}
void Foo() {
std::cout << "C: " << member_ << std::endl;
}
};
int main() {
B *b = new B("hello");
C *c = new C("world");
b->Foo();
c->Foo();
D d = (*b) + (*c);
d.Foo();
delete b;
delete c;
return 0;
}
The output of this program is:
B: hello
C: world
D: hello world
I have following code on c++:
#include <iostream>;
#include <vector>;
class A
{
public:
A(int n = 0) : m_n(n) { }
public:
virtual int value() const { return m_n; }
virtual ~A() { }
protected:
int m_n;
};
class B
: public A
{
public:
B(int n = 0) : A(n) { }
public:
virtual int value() const { return m_n + 1; }
};
int main()
{
const A a(1);
const B b(3);
const A *x[2] = { &a, &b };
typedef std::vector<A> V;
V y;
y.push_back(a);
y.push_back(b);
V::const_iterator i = y.begin();
std::cout << x[0]->value() << x[1]->value()
<< i->value() << (i + 1)->value() << std::endl;
system("PAUSE");
return 0;
}
The compiler returned result: 1413.
I am little bit confused, because I thought the right result would be 1414 (as the function virtual). How do you explain this program behavior?
You are slicing the object, in order to get polymorphism you need to use either a pointer or a reference. This example keeping as close as possible to your original example and using a pointer will act as you wanted:
const A a(1);
const B b(3);
typedef std::vector<const A*> V;
V y;
y.push_back(&a);
y.push_back(&b);
V::iterator i = y.begin();
std::cout << (*i)->value() << std::endl ;
++i ;
std::cout << (*i)->value() << std::endl ;
To show briefly how the object slicing works here:
const A a(1);
const B b(3);
std::vector<A> y; // so y contains objects of type A
y.push_back(a); // y[0] is copy-constructed from a
y.push_back(b); // y[1] is copy-constructed from b
Note that in both push_back calls, it's always an A being constructed, via the automatically-generated A::A(const A&) copy constructor.
Note also that a B is-a A, which is to say b can be implicitly cast to an A and passed into the same copy-constructor.
So, y[1] is an instance of A with the m_n value copied from b, but its virtual function is still A::value. If you have constructor B::B modify the value when it is initialized, instead of when it is returned, you'll see the result you expect.