I have to classes, A and B. There are actually many other classes that all share a pointer to A, because A is sort of a manager that controls all the other classes during runtime.
The idea is that A and B both open a bunch of file I/Os during their lifetime, but any class can request the execution to stop. At this point, I'd like to gracefully close all the files which are open. B and all other classes all contain a member function like
void B::CloseFile()
So my idea was that I first instantiate A which contains an empty vector of CloseFile function pointers, then instantiate all the subsequent classes that "register" their own Close functions in A's vector. Then any class can call a stop, and call A's (since all classes have a pointer to A) CloseAll function, which traverses the vector and closes everything its got.
I tried to prototype this in a simple example and I'm getting stuck. Here is the code that doesn't work, the last line throws an error.
// Example program
#include <iostream>
#include <string>
using std::cout;
class B;
typedef void (B::*bfnptr)();
class A {
public:
// Some methods
void SetBfn(bfnptr new_ptr) { do_b_ = new_ptr; };
// Some vars
int a_ = 0;
bfnptr do_b_ = nullptr;
};
class B {
public:
// More methods
void ZeroMe() { b_ = 0; };
void SetA(A* obj_a) { aptr_ = obj_a; };
void IncMe(int op) { b_ += op; };
// More vars
A* aptr_ = nullptr;
int b_ = 1;
};
int main()
{
// Two instances
A obj_a;
B obj_b;
// Setup B to point to A
obj_b.SetA(&obj_a);
// Manipulate A through B
cout << "A var initially: " << obj_a.a_ << "\n";
obj_b.aptr_->a_ = 10;
cout << "A var is now: " << obj_a.a_ << "\n";
// Object b can do things
cout << "B var initially: " << obj_b.b_ << "\n";
obj_b.IncMe(1);
cout << "B var is now: " << obj_b.b_ << "\n";
// Set A to point to a function in B
obj_a.SetBfn(&obj_b::ZeroMe);
}
When I compile this with C++14, I get the error
In function 'int main()':
51:19: error: 'obj_b' is not a class, namespace, or enumeration
This is actually not my question; I'm not sure why this is happening. The actual question I wanted to ask was how to handle the circular dependency between classes A and B. But why is that error happening?
Related
Changing values of classes/structs inside classes are a mystery to me. I tried to do some research today and came up with the following solution. I wonder if this is a proper way for a function to change stuff inside the class. Is there a need to for this to be somehow done with pointers? Is there a more proper way to accomplish this?
#include <iostream>
int main()
{
class Someclass {
private:
int Integer;
public:
Someclass(int i):
Integer(i){} //CTOR
struct Somestruct {
int a, b;
};
Somestruct Mystruct;
void func(){
Mystruct.a = Integer/2;
Mystruct.b = Integer*2;
};
};
Someclass A(10);
A.func();
std::cout << A.Mystruct.a << " " << A.Mystruct.b << std::endl;
}
The reason I am writing this code, is because I want to parse a file, starting from the line "Integer" into a customly defined struct "Mystruct" which this class should somehow deliver me. Is this an acceptable way to write such a code?
I understand that your question is about encapsulation, being understood that the inner struct is a data holder and the outer class has to manage it somehow.
Weaknesses of your design
In your design, Mystruct is public. So anything outside Someclass could access the data, but also change it. This is error prone, as there is no guarantee that the outside code doesn't break some invariant of the structure.
Ways for improvement
The cleanest thing would certainly to make some getters and setters to access the data. But with 30 members, it's a lot of code.
If your construction process initialises the struture's data, a second approach could be to limit outside access to read-only. You'd do that by making Mystruct private and offering a function returning a const reference:
class Someclass {
Somestruct Mystruct;
public:
...
const Somestruct& get() { return Mystruct; }
};
std::cout << A.get().a << " " << A.get().b << std::endl;
Online demo
Nevertheless before going into that direction, I'd check if access to the structure's raw data couldn't be encapsulated, for example by providing functions that manage the data without need to know the internals:
class Somestruct {
...
public:
ostream& show_simplified_specs(ostream& os) {
os << a << " " << b;
}
}
A third approach could be to use the builder design pattern to encapsulate the construction process of a Someclass based on Somestruct and other parts.
Pointers ?
Pointers should be avoided if possible. For example, suppose you have a vector of Someclass to keep all these classes in memory. At a moment in time, you get a pointer to an element's Mystruct. Suppose you'd then add a new item to the vector: all the previous pointers might get invalidated.
This same risk potentially exist with references. But I think that while it's a common idiom to cache a pointer returned by a function,in practice it's less common and appealing to copy a reference returned by a function.
Is this what you're looking for? I'm not much confident I understood you right.
template <int I>
struct Someclass;
template <>
struct Someclass<1>
{
int Integer = 1;
int a, b;
void func()
{
a = Integer/2;
b = Integer*2;
}
};
template <>
struct Someclass<2>
{
int Integer = 2;
int a, b, c;
void func()
{
a = Integer/2;
b = Integer*2;
c = Integer*Integer;
}
};
int main()
{
Someclass<1> A;
A.func();
std::cout << A.a << " " << A.b << std::endl;
Someclass<2> B;
B.func();
std::cout << B.a << " " << B.b << " " << B.c << std::endl;
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;
}
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.
For example, in this piece of code, if line [a] is commented out, the output is 0.
inh2.cpp
#include<iostream>
using namespace std;
class A {
public:
int x;
A() { x = 10; }
};
class B : public A {
public:
int x; // <--------- [a]
B() { x = 0; }
};
int main() {
A* ab = new B;
cout << ab->x << endl;
}
results from gcc
$ g++ inh2.cpp
$ ./a.out
10
$
I have two questions:
How does ab->x resolve to 10 in the above case? The object is of type class B, and thus should value to 0.
Why does commenting Line [a] change the behaviour of the code? My reasoning is that x would have anyways been inherited, which should result in same behaviour.
My reasoning for Q #1 above:
ab points to the memory location of an object of class B. It is a physical object in the sense that all the variables with their values are assigned memory.
Variable x within this object stores value 0.
When ab->x is done, ab tells us the memory location of the object, and we go look inside it to find that x is 0. So we should print 0.
Where am I wrong here?
Yes, it is of type B, but you are assigning it as a pointer to an A, and therefore it is using the x defined on A (as when we're dealing with a pointer to A, we don't know that B even exists, even though that's what you allocated).
When you comment out the line, during the construction phase, As constructor is called first, then Bs constructor, which sets x (in its base class) to 0. There is only one x at this point, and Bs constructor is called last.
Making a some small modifications:
#include <iostream>
using namespace std;
class A {
public:
int x;
A()
:x(10)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
virtual ~A() {}
};
class B : public A {
public:
int x; // <--------- [a]
B()
:A()
,x(0)
{
std::cout << __FUNCTION__ << std::endl;
std::cout << x << std::endl;
}
};
int main() {
A* ab = new B;
cout << "ab->x: " << ab->x << endl;
cout << "ab->A::x " << ab->A::x << endl;
B* b = dynamic_cast<B*>(ab);
cout << "b->x: " << b->x << endl;
cout << "b->A::x " << b->A::x << endl;
cout << "b->B::x " << b->B::x << endl;
}
This gives you:
A
10
B
0
ab->x: 10
ab->A::x 10
b->x: 0
b->A::x 10
b->B::x 0
This demonstrates that:
ab->x refers to A::x because ab is of type A* and there is no such thing as a virtual variable. If you want polymorphism, you'll have to write a virtual int get_x() const method.
B::x hides A::x. This is a bad idea and should be avoided. Consider using a more meaningful name for your member variables and establish whether you can reuse the base class's variable before introducing a new one.
Casting to a B* allows you access to B's members as well as A's. This should be self-explanatory.
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).