Lately I've been working in some project and the thing is that we've encountered a situation in which we need to be able to do stuff like this.
#define TYPED(Type) \
virtual Type *typedThis() const { return (Type*) this; }
class A {
public:
TYPED(A)
virtual void describe() { std::cout << "I am type A\n"; }
static int x;
};
int A::x = 1;
class B : public A {
public:
TYPED(B)
virtual void describe() { std::cout << "I am type B\n"; }
static int x;
};
int B::x = 2;
int
main(int argc, char** argv)
{
B* b = new B();
A* b2 = b;
b->describe();
b2->describe();
std::cout << b->typedThis()->x << std::endl;
std::cout << b2->typedThis()->x << std::endl; // AQUI DEBERIA DAR 2 !! :c
}
This is of course just a toy example. The basic idea of what we would like to do is to define a function typedThis() who does the casting of the pointer into the correct type and then access to the correct variable x, and printing out 2 instead of 1.
However, the output is the following:
I am type B
I am type B
2
1 //Here should also be 2
What I find really interesting is that the virtual method describe() seems to be working the way we want. Therefore, I could infer that the method typedThis() is also working the way we would like to. But if so, why does C++ see this pointer as an A* instead of an B*. If C++ saw this pointer like a B* then it would have used the correct variable x. Can someone explain this to me?
I tried using CRTP, however I don't feel like this would make things easier, because in the project we will be using a lot (A LOT) of different classes who derive between them constantly, I saw some articles of how to use CRTP when having multiple inheritance, however they are really messy and hard to integrate with what we have so far.
I removed all distractions from the example:
class A {
public:
virtual A *typedThis() const { return (A*) this; }
static int x = 1;
};
class B : public A {
public:
virtual B *typedThis() const { return (B*) this; }
static int x = 2;
};
int main()
{
B* b1 = new B;
A* b2 = b1;
std::cout << b1->typedThis()->x << "\n";
std::cout << b2->typedThis()->x << "\n";
}
typedThis doesn't do anything.
b1->typedThis() returns a B* which points to a B.
Likewise, b1 itself is a B* which points to a B.
b2->typedThis() returns an A* which points to a B.
Likewise, b2 itself is an A* which points to a B.
So b1->typedThis() is the same as b1 and b2->typedThis() is the same as b2, and the last two lines of the example are equivalent to the following:
std::cout << b1->x << "\n";
std::cout << b2->x << "\n";
Also take note that your C-style casts discard the const qualifiers of the objects.
Related
I can't seem to find anything that deals with this type of operation.
I have a class TextButton : public TextDecorator class that I want to overload the implicit conversion operator for. The TextButton class contains a BasicButton pointer that I want to give access to.
Overloading the TYPE conversion operator works fine, however it doesn't do what I want it to do when I am using a TextButton* to perform the cast on.
This code shows what I mean :
#include <iostream>
using std::cout;
using std::endl;
class A {
public :
void DoThis() {cout << "a is " << this << endl;}
};
class B {
A* a;
public :
B() : a(new A) {
cout << "a is " << a << endl << endl;
}
~B() {delete a;}
operator A*() {return a;}
};
int main(int argc , char** argv) {
B b;
A* a1 = (A*)b;/// Implicit conversion works fine for objects of type B
A* a2 = (A*)&b;/// Implicit conversion works, but is incorrect for objects of type B*
A* a3 = static_cast<A*>(b);/// Fine, not what I want
/// A* a4 = static_cast<A*>(&b);/// What I want, but illegal
/// "invalid static cast from B* to A*"
a1->DoThis();
a2->DoThis();
a3->DoThis();
/// a4->DoThis();
return 0;
}
The output ((un)luckily it didn't crash) shows why it is bad :
c:\ctwoplus\progcode\test\Cast>cast.exe
a is 0xea1718
a is 0xea1718
a is 0x61ff20
a is 0xea1718
So what I want is to make this possible :
TextButton* tb = MakeTextButton(...);
BasicButton* button_access = (BasicButton*)tb;
And have it work correctly.
Ideas?
I am trying to understand object oriented programming using c++. The following is a minimal example for which the result is not what I naively expect:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
A a_main(b_main);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
The last cout statement does not make sense to me. In the second to last line, I set the value of the object to be 2, so why does this not print 2? Looking at some similar questions on Stack Exchange, I found some suggestions to make A and B be friends of each other. I tried adding friend class A in class B and friend class B in class A, but this did not work. In my understanding, adding the friend statements should be unnecessary since I have the get_b() method in class A. I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
Can anyone explain to me why the program is not producing the intended result and also how to obtain the desired result (that is, the last cout statement prints 2)?
Note: I also experimented with the following. I made the private variable b of class A be public:
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B b; // This is now public
//B get_b() { return b; } // This is no longer needed
private:
};
int main(){
B bmain(5);
std::cout << bmain.get_val() << std::endl;
A amain(bmain);
std::cout << amain.b.get_val() << std::endl;
amain.b.set_val(2);
std::cout << amain.b.get_val() << std::endl; // Works!
return 0;
}
And now I obtain the desired result. Is this how the code should be implemented as opposed to the first code snippet? I would like to have a get_b() method as in the first code snippet, but if this is not the correct way of going about this, please let me know.
In the second to last line, I set the value of the object to be 2, so why does this not print 2?
Because you return a copy of the B object in a_main with the get_b() method. What happens is that the b variable in a_main is copied, i.e. another object of class B, identical to the b member, is created, and returned to the caller. Then, that new B object is modified. But it has no connection to the original b in a_main. This has little to do with visibility and member access.
However, in the second example, you expose the b member in a_main and directly operate on that object without making a copy of it, thus the successful result. What the public modifier changes is that it allows you to access the b object directly, hence the effect.
I found some suggestions to try passing the object of type B in by reference to the constructor of A: A (B& b) : b(b) {;} but this did not work either.
That isn't going to work. What happens when you do so, is that the A::b is initialized using the value that is passed by reference, true. But the reference only leads to no additional copy of b passed to the constructor being made. This reference does not create a link between the b passed to the constructor and A::b. It's on the other end, so to say.
By the way, A (B& b) : b(b) {;} that the c'tor parameter name is identical to the member name is a bad practice. It's a good idea to have them named similarly, but still, add e.g. an underscore: A (B& _b) : b(_b) {;}
If you want to achieve the same result in the first snippet, return a reference to b like so:
B& get_b() { return b; }
Still, this is undesirable, because you expose a private member of class A just to allow clients of A to modify a certain property of that member. Better provide a method in A to set the val property of A::b without giving full access to A::b.
Definitely see this: What's the difference between passing by reference vs. passing by value?
and maybe this: Java and C++ pass by value and pass by reference
because I have a feel that you're coming from Java and expect pass-by-reference in C++ by default.
get_b returns a copy of your private variable b, not the actual variable. If you want to be able to access it, you need to return a reference to b so that the returned value can be manipulated. Your get_b definition should look like this:
B& get_b() { return b; }
if that is what you expect to do. However, this is not usually a desirable solution. If you are going to be actively changing the value of b you should write a set_b function to manipulate the variable. And if you are really working with the variable a lot, reading and writing values to it, you should keep it public for fast access.
Just for the sake of completeness, you can solve this problem as a C programing problem rather than using all the fancy references in C++ programing. When you get b_main from a_main, the returned object does not occupy the same memory address.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B get_b() { return b; }
private:
B b;
};
int main(){
B b_main(5);
B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
B bt = a_main.get_b();
addrb = &(bt);
std::cout << a_main.get_b().get_val() << std::endl; // Prints 5, which makes sense
std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b().set_val(2);
std::cout << a_main.get_b().get_val() << std::endl; // Why does this not print 2?
return 0;
}
Notice the difference in address of the new cout statements. One way to fix this is to return pointers rather than b itself. i.e.
#include <iostream>
class B {
public:
B (int val) : val(val) {;}
int get_val() { return val; }
int set_val(int a) { val = a; }
private:
int val;
};
class A {
public:
A (B b) : b(b) {;}
B* get_b() { return &b; }
private:
B b;
};
int main(){
B b_main(5);
//B* addrb = &b_main;
std::cout << b_main.get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of b_main: "<<addrb<<std::endl;
A a_main(b_main);
//B bt = a_main.get_b();
//addrb = &(bt);
std::cout << a_main.get_b()->get_val() << std::endl; // Prints 5, which makes sense
//std::cout<<"Address of a_main.get_b(): "<<addrb<<std::endl;
a_main.get_b()->set_val(2);
std::cout << a_main.get_b()->get_val() << std::endl; // Why does this not print 2?
return 0;
}
I am building an interface, where it would be a little bit inconvenient to use separate variables to access individual interfaces, it would be great if somehow I could create a union of the two.
In a file:
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
In another file:
#include <path to A, B>
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
And another file:
#include <declaration of A and B, but not C>
void doSth(A* a)
{
B * b = dynamic_cast<B*>(a);
/* I can only call auu with a */
a->auu();
/* I can only call boo with b */
b->boo;
/* Something like this would be ideal: */
<??? type> * C_interface = dynamic_interface_cast<B*>(a)
C_interface->auu();
C_interface->boo();
}
So is there to call both auu and boo through only one pointer variable and without the knowledge of C's implementation (not casting it to )? Also I'd like to avoid creating inheritance hierarchy that is NOT in connection with class C.
Probably the answer is no, however I'm curious if an idea like this has come up from the side of the language developers because to my primitive mind it's not a so far fetched idea.
EDIT:
In real, A and B are abstract. A is a Simulation object that has methods like size() and length(). B is an IO interface, implementing getters and setters, but it doesn't know about sizes so I have to use both interfaces in many calculations. C is a specialized Simulation that implements the former 2.
EDIT:
I rewrote the question, maybe it actually makes sense now.
I'll ilustrate the point I made in my comment. It's perfectly legal to cast between siblings, as long as the actual object is derived from both.
#include<iostream>
using namespace std;
struct A{
virtual int auu() { return 41; }
};
struct B{
virtual int boo() { return 43; }
};
struct C : public A, public B{
int auu() { return 20; }
int boo() { return 22; }
};
void take_B(B* bp)
{
cout << bp->boo() << endl; // expected
cout << "(The base class would say "
<< bp->B::boo() << ")" << endl; // base class implementation
A *ap = dynamic_cast<A*>(bp);
if(!ap)
{
cerr << "weird, this cast should be possible!" << endl;
}
else
{
cout << ap->auu() << endl; // should work
cout << "(The base class would say "
<< ap->A::auu() << ")" << endl; // base class implementation
}
}
int main()
{
C c;
take_B(&c);
cout << endl << "... and again:" << endl;
// just to clarify: The actual pointer type is irrelevant.
B *bp = &c;
take_B(bp);
return 0;
}
Consider:
struct V {
V(int i) {
std::cout << "initialized v" << '\n';
}
};
struct A {
A() {
std::cout << "initialized a" << '\n';
}
};
struct B : virtual V, virtual A {
B(int i) :V{i} {
std::cout << "initialized b" << '\n';
}
};
class C : virtual V, virtual A {
public:
C(int i) : V{i} {
std::cout << "initialized c" << '\n';
}
};
class D : virtual public B, virtual public C {
public:
D(int i, int j) :V{i}, B{i}, C{j} {
std::cout << "initialized d" << '\n';
}
};
If I initialize D in main(), like this:
int main() {
D* d = new D{3,3}; //ok
B* b = new D{3,3}; //ok
C* c = new D{3,3}; //undefined
delete d;
delete b;
delete c;
}
But if I use a factory, like this:
C* factory() {
return new D{3,3};
}
int main() {
factory(); //ok
}
I can't figure out why it's causing undefined behavior when I initialize D through C in main() but works fine when I use other functions. What's wrong with C? Isn't it just the same as B?
Edit: So my code runs fine on this demo as I think it should. If there's nothing wrong with my code, is there a problem with my development environment? I'm using the latest mingw-w64 with eclipse CPP.
You are looking for the undefinedness in all the wrong places.
delete b;
delete c;
Both lines invoke undefined behavior, by deleting a derived class object (a D) through a pointer to base class (a B* or C*) with no virtual destructor. Give them one (e.g., by adding virtual ~V() = default; to V), and the crash should disappear.
This is why it's important to verify that the code you post here in fact reproduces the crash you are seeing when compiled and run. Someone would probably have spotted the problem in less than 5 minutes if the full code were available at the beginning. Instead, we spent 45 minutes trying to reproduce the problem.
I have a class Model:
class Model
{
...
boost::shared_ptr<Deck> _deck;
boost::shared_ptr<CardStack> _stack[22];
};
Deck inherits from CardStack.
I tried to make _stack[0] point to the same thing that _deck points to by going:
{
_deck = boost::shared_ptr<Deck>(new Deck());
_stack[0] = _deck;
}
It seems that the assignment to _deck of _stack[0] results in a copy of _deck being made. (I know this because modifications to _stack[0] do not result in modifications to _deck.) How can I get them to point to the same thing?
Ok - no copy constructor is being called. I have verified this by implementing it and seeing if it gets called - it doesn't.
However - I have a function that operates on CardStack objects:
void TransferSingleCard(CardStack & src, CardStack & dst, Face f)
{
if( !src._cards.empty() )
{
src._cards.back().SetFace(f);
dst.PushCard(src._cards.back());
src._cards.pop_back();
}
}
Now - when I call:
{
TransferSingleCard(*_stack[DECK], _someotherplace, FACEDOWN);
std::cout << *_stack[DECK];
std::cout << *_deck;
}
I get this output (where std::cout on a CardStack will print out the size of that stack):
Num(103) TOP
Num(104) TOP
... so I've concluded (incorrectly?) that _stack[DECK] points to something different.
The Deck
class Deck : public CardStack
{
public:
Deck(int numsuits=2, StackIndex index = NO_SUCH_STACK );
Deck::Deck( const Deck & d);
int DealsLeft() const;
void RecalcDealsLeft();
private:
int _dealsleft;
};
Not clear what you are asking about - consider this code:
#include <iostream>
#include "boost/shared_ptr.hpp"
using namespace std;
struct A {
virtual ~A() {
cout << "destroyed" << endl;
}
};
struct B : public A {
};
int main() {
boost::shared_ptr<B> b( new B );
boost::shared_ptr<A> a;
a = b;
}
Only one "destroy" message appears, indicating that no copy has been made.
This example - derives from #Neil's answer, tries to emulate what you say is happening. Could you check that it works as expected (A and B have the same count) on your system.
Then we could try and modify this code or your code until they match.
#include <boost/shared_ptr.hpp>
#include <iostream>
class A {
public:
virtual ~A()
{
std::cerr << "Delete A" << std::endl;
}
int _count;
void decrement()
{
_count --;
}
};
class B : public A {
public:
virtual ~B()
{
std::cerr << "Delete B" << std::endl;
}
};
int main()
{
boost::shared_ptr<B> b(new B);
b->_count = 104;
boost::shared_ptr<A> a;
a = b;
a->decrement();
std::cerr << "A:" << a->_count << std::endl;
std::cerr << "B:" << b->_count << std::endl;
return 0;
}
EDIT:
So from the comment, we know the original pointers are correct, so now we need to trace.
Either:
log pointers to see when they change.
Use watchpoints in a debugger to see when the pointer changes.
Use a third shared pointer to see which pointer is changed.
Introduce a function that changes both pointers at the same time.
I think the problem is that you're assigning between different types here. boost::shared_ptr is a template and templates are not polymorphic even if the type in them is. So what's happening is that your compiler sees the assignment from boost::shared_ptr<Deck> to boost::shared_ptr<CardStack> and notices that it can make the assignment by calling the copy constructor for CardStack to duplicate the Deck object.
I think what you want the assignment to look like is something like this:
_stack[0] = boost::static_pointer_cast<CardStack>(_deck);
Which will do the conversion the way you expect it to.
I think you may want shared_array for _stack . . . Take a look at the documentation on shared_ptr;from boost.org, specifically:
http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/shared_ptr.htm
"Normally, a shared_ptr cannot
correctly hold a pointer to a
dynamically allocated array. See
shared_array for that usage."
Also, be aware of the T* get() function (not to be used without good reason) which returns the raw pointer being held by the managed pointer (shared_ptr in this case).