I have 3 questions about below code:
class cb
{
public:
int y_;
class iterator
{
public:
//void func() { y_ = 5; } // (1)
private:
int x_;
//cb a; // (2)
};
void funcCB() { }
};
class Human
{
public:
void func() const {
cb c; // (3)
c.funcCB();
}
// (4)
};
1- Why i can't use Outer class's member variable y_ inside Inner class as in (1)?
2- Why i can't create object from Outer class inside inner class as in(2) but i can only create pointer and reference?
3- Why if i moved the line at (3) cb c; to line at (4) i get compile error ?
You can't use outer class field because it's not like your class iterator have direct access to it. First of all why would you want to have access to that field? I would think about redesign your solution first. But as you wish here is what you could do to solve the issue. You would need to have reference to the object which is your parent
class cb
{
public:
cb(): it(*this) {} // Passing the reference to ourself for iterator object init to have access in iterator class access to y_ field.
int y_;
class iterator
{
public:
iterator(cb& ob): a(ob) {}
void func() { a.y_ = 5; }
private:
int x_;
cb& a; // Reference to parent object
};
iterator it; // Added because I don't see the point where you don't want to have that object in your cb class.
void funcCB() { }
};
I'm not sure what would you like to achieve here. It will throw incomplete type because you will want to create cb object in which you will create iterator object in which you will create cb object in which again you will create iterator so you would get infinite recursion (if I understand that correctly). When you point iterator to concrete object it will stop the cycle.
You should change in class cb funcCB to be void funcCB() const {} because otherwise in class Human it is understanded that in func() which is const function you want to call funcCB() which will not modify the object c from Human class and there is a difference between qualifiers because you don't have const function in that case. You can also delete const qualifier in Human class for func and this will also work. Error here happens when you don't change qualifiers, because it is different when you have const function in which you create some object to further use and when you have object as a class field and you call function which cannot change the state of Human class and CB class don't have equivalent of const function for funcCB.
Why i can't use Outer class's member variable y_ inside Inner class as in (1)?
Because y_ is a non-static data member of class cb, meaning we must access it on a particular cb object. But here comes the problem. The assignment statement y_ = 5; is equivalent to:
vvvv--------------->this points to an object of type iterator and not cb
this->y_ = 5;
In the above shown equivalent statement, the this pointer points to the current instance of type iterator and not cb. But since to access y_ we must use a cb type object, we get the mentioned error.
Basically y_ should be accessed on an object of type cb. For example, you can make func to have a parameter of type cb& and then access y_ as shown below:
class cb
{
public:
int y_;
class iterator
{
public:
//------------vvv------------------->pass object of type cb by reference
void func(cb& it) { it.y_ = 5; } // (1) OK NOW
//----------------------^^---------->access member y_ on object it
private:
int x_;
};
void funcCB() { }
};
Why i can't create object from Outer class inside inner class as in(2) but i can only create pointer and reference?
Because at point #2 the class cb is incomplete and so at point #2 we cannot create a non-static data member of type cb. This can be seen from complete type documentation which states:
Any of the following contexts requires type T to be complete:
declaration of a non-static class data member of type T;
This means that at point #2 we cannot have a declaration for a non-static data member of type cb but we can still have a declaration for a non-static data member of type cb& or cb* as we can have a pointer or a reference to an incomplete type like cb.
Why if i moved the line at (3) cb c; to line at (4) i get compile error ?
If you moved line #3(cb c;) to line #4, you won't get any compile time error. Demo
class Human
{
public:
void func() const {
//cb c; // (3)
//c.funcCB();
}
cb c; // (4) perfectly fine
};
Forgive me if I don't quite get this -- my C++ is a little rusty.
Regarding question (1) -- Have you tried the "this" keyword?
E.g.,:
void func() { this->y_ = 5; }
Here is an example almost identical to yours:
'this' pointer in C++
For question 2, you're asking for a recursive inclusion of an object. That's like saying, What is an Onion? It is a Peel that contains an Onion. Well, that Onion inside is also a Peel that contains an Onion, then a Peel, then an Onion, etc. Without some mechanism to halt (an Onion might be a Core, which contains nothing), the first instantiation of the Onion object would loop infinitely until all memory was used up.
As a reference, the memory can be retrieved only when needed, and not before.
For question 3, I'm taking the lazy way out to say, them's just the rules.
UPDATE:
I'm not at work now, so I had more time to do a little more research. As I've said, my C++ is a little rusty.
Essentially for Q 1, what you're attempting to do is access the members of class "cb" from class "iterator". My research indicates that, just because "iterator" is a subclass of "cb", it doesn't get any special access privileges. So you can not access "cb::y_" from "iterator" and you can not use "this->y_" either. Methods (functions) inside the class can access "y_" directly. Sub-classes can not.
Note the following which compiles successfully:
class cb {
public:
int y_;
class iterator {
public:
void func() {
cb *z = new cb();
z->y_ = 5;
} // (1)
private:
int x_;
cb *a; // (2)
};
void funcCB() { }
};
class Human
{
public:
void func() const {
cb c; // (3)
c.funcCB();
}
// (4)
cb *z;
};
This probably is not what you're attempting to accomplish, but I expect that what you want to do can not be done the way you want. Your best bet would be to implement the "iterator" as its own class distinct from "cb" and make it a "friend" class of "cb". Or maybe better yet, and simpler, just include a set of iterator methods inside the class. The methods will have full access to all of the class attributes.
Also note the pointer reference to "cb". It does not compile as a straight object instantiation in a sub-class. Again, the Onion issue.
On a side note, remember that C++ is not Pascal. It's not Java. It can do sub-classes, but as you can see, it doesn't do them very well, or at least, it doesn't do them the way other languages do them. You're better off creating every class completely distinct from every other class, other than normal inheritance. That's sort of unofficially "The C++ Way."
Related
I'd like to use a pointer to a class data member that has an inherited type. The code is pretty straightforward, I have an object (A) with a data member which class (Integer) inherits another class (Type), and I'd like to create a pointer to this data member using the parent class (Type*) instead of the base class (Integer) :
class Type
{
public:
Type() {}
};
class Integer : public Type
{
public:
Integer() : Type() {}
int value;
};
class A
{
public:
A() { p_value.value = 0; };
Integer p_value;
};
int main()
{
Type* aType = &A::p_value;
return 0;
}
the code on ideone
I have a compilation error:
error line: Type* aType = &A::p_value;
error: cannot convert 'Integer A::*' to 'Type*' in initialization
After a lot of fiddling with the code I couldn't make it work, what am I doing wrong ?
Basically types of pointers aren't matching. &A::p_value is of type A::*Integer (or Integer A::* as compiler nicely states), while Type* is... just Type*.
Former (A::*Integer) is a pointer to member and can be used like this:
A a1;
A* a2 = new A;
A::*Integer a_member = &A::p_value;
a1.*a_member = 1;
a1->*a_member = 2;
// now a.p_value == 1 a->p_value == 2
Meanwhile Type* is just pointer to Type object - since Type class hierarchy is separate from A class hierarchy no casting between classes make sense. And here you want to cast from pointer to member to pointer to class. You most likely wanted to to something like this:
int main()
{
A a;
Type* aType = &a.p_value;
return 0;
}
Difference lies in what they do. Pointer to class will look up in memory beginning of your object, then use information about where in this object particular member/virtual function pointer lies, go there and return value.
We use them to obtain data or call virtual method basing on object's address.
In the other hand pointer to member only knows the difference between beginning of object's memory and sought data position. So you need to have both object's address and the delta to figure out location of the data:
(object_by_value).*(pointer_to_member);
(object_by_pointer)->*(pointer_to_member);
By the way they work you can understand that casting one into another will only produce garbage and compiler saves you from that mistake with a warning:
cannot convert 'Integer A::*' to 'Type*' in initialization
Suppose I have class B which gets a value 'v' in the constructor from another class A. How can I read this value from class C?
Class C will be instantiated on demand, but A has created B and passed the 'v' already. 'v' will change in every instantiation. I have tried to make 'v' static in Class B. Would it work? I could not implement it properly.
Class A {
public:
int* v;
B b1;
A(int* var) : v(var), b1(var) {};
}
How to access the same version of 'v' from a C class?
I can define B and C however I like in order to achieve the goal. But I cannot change A for that purpose.
You need a (public) static member
class A { //let's stick with your naming convention!
public:
static int a;
}
A::a = 4;
However allowing people to change A::a means that your program will probably end up relying on a global unencapsulated state... which is usually a sign of a bad design.
If you member was const however you are really relating a constant to your class, which is not so bad.
class A {
public:
static const int a = 4;
}
std::cout << "A:a is always " << A::a << std::endl;
EDIT BASED ON UPDATED QUESTION
If you require help with building a class I would recommend that you use a factory of some kind. If I understand your requirement you want to be able to inject a value into every class A and class B instance. This value "v" is based on a Class C.
So...
class C {
private:
// up to you where you implement the getUniqueNumberForNow function
// (global free function for example)
static const int v = getUniqueNumberForNow();
public:
static A createA(){
return A(v);
}
static B createB(){
return B(v);
}
}
The getUniqueNumberForNow() function just gets whatever your value should be. It will be then stored in class C and can be used during the creation of A an\or B. Now just make A and B's CTORs private and make C a friend of both and you will have only one way to create an A or B, and it will always use the correct value.
See NeilMonday's link in the comments below for info on friend classes.
Last thing is if you want to have the value change for every instantiation of A you can just do this in the factory:
static A createA(){
return A(getUniqueNumberForNow());
}
However if that is really what you want then just do this:
class A {
public:
A() : val (getUniqueNumberForNow()), b(B(val)){}
}
You cannot access a 'v' which has never passed to the class. Instead you can make a static copy of it as a member in your class A. It will update every time A is instantiated like this:
Class A {
public:
int* v;
static int* staticv;
...// Constructor etc
}
in your .cc code of A:
int* A::staticv;
...
A::staticv=this->v;
now any class can access to this value by:
A::staticv;
I have a base class that updates an extern reference, and I want to build an inherited class that would embed this reference as a member. A kind of default initialization of the reference.
I came up with the following solution:
#include<iostream>
class Statefull
{
public:
Statefull( int& ref ) : _base_ref(ref) {}
int& _base_ref;
// update the extern variable
void work() { std::cout << ++_base_ref << std::endl; }
};
class Stateless : public Statefull
{
public:
// use a temporary allocation
Stateless( int* p = new int() ) :
// we cannot initialize local members before base class:
// _dummy(), Statefull(_dummy)
// thus, initialize the base class on a ref to the temporary variable
Statefull(*p),
_tmp(p),
_dummy()
{
// redirect the ref toward the local member
this->_base_ref = _dummy;
}
int* _tmp;
int _dummy;
// do not forget to delete the temporary
~Stateless() { delete _tmp; }
};
int main()
{
int i = 0;
Statefull full(i);
full.work();
Stateless less;
less.work();
}
But the need of a temporary allocation in a default argument of the constructor seems quite ugly. Is there a more elegant way to achieve this kind of default initialization while keeping a reference in the base class constructor?
Well, the Stateless class is violating the rule of three. But I'll assume that's because this is just sample code to exhibit the real problem.
Now, to actually address the problem: it's perfectly valid to bind a reference to an uninitialized variable, as long as its value is not used before initialization actually happens.
Stateless() : Statefull(_dummy), _dummy() {}
The present solution works, but it seems there's some misunderstanding about why it works.
// redirect the ref toward the local member
this->_base_ref = _dummy;
You cannot "redirect" references. You can only bind a reference once: upon initialization. Assigning to a reference assigns to the object it refers to. In this case, this->_base_ref = _dummy is exactly the same as *_tmp = _dummy : it assigns the value of _dummy to *_tmp. _base_ref, however, still refers to *_tmp (you can test this with assert(&_base_ref == tmp)).
I think this might work:
StateLess(): Statefull(*new int) {}
~StateLess() { delete &_base_ref; }
You can't do without temporaries, but they don't have to be in the classes definitions.
Everything can be solved using some more classes
class StateForStateful
{
protected:
int state;
};
class Stateless: private StateForStateful, public Stateful // order is important
{
public:
Stateless():Stateful(this->state) {}
};
This is probably best shown with example code. The following fails to compile with g++:
struct Base {
};
struct Derived : public Base {
};
struct Container {
Derived data_;
};
int main(void) {
Base Container::*ptr = &Container::data_;
}
I get the following error: invalid conversion from 'Derived Container::*' to Base Container::*'.
Is this not allowed by the language? Is this a compiler bug? Am I using the wrong syntax?
Please help!
Some background as to why I'm trying to do this: I have several member data pieces that I want to use primarily as their derived types, but I want to be able to populate them through some common code. Data will be coming in an arbitrary order and have a string label that I would use to select the appropriate member data to populate. I was planning on creating a std::map<std::string, Base Container::*> to assign data to each member through a common interface. I'd like to avoid have a giant if else construct to find the right member data.
This is not a compiler bug, you can't do that. (But you can assign a Base::* to a Derived::*).
I don't see any good reason for the limitation (excepted that to handle the case of multiple inheritance, that would complicate even more the representation of a member pointer).
There are a lot of fairly complex, some not-well-explained, and a few flat wrong answers in this thread.
But the problem, it seems to me, is that there simply isn't a Base member within Container -- there is a Derived member. You can't do this:
Base Container::*ptr = &Container::data_;
...for the same reason you can't do this:
int a;
long* pl = &a;
In the second example, the object isn't a long, it's an int. Similarly, in the first example the object isn't a Base, it's a Derived.
As a possibly tangential point, it seems to me like what you really want to do is have Base be an abstract class, and have Container have a Base* rather than a Derived member.
Pointers to members in C++ are not really pointers but more like offsets to given member and are specific to the type, so what you are trying to do is not really supported.
Here's a decent discussion here on Stackoverflow C++: Pointer to class data member.
You just need to write:
Base* ptr = &container.data_;
but container has to be an instance of Container, so you have to create one variable of that type somewhere.
You cannot convert C::*A to C::*B even if there is a conversion possible between A and B.
However, you can do this:
struct Base
{
virtual ~Base() {}
virtual void foo() { std::cout << "Base::foo()\n"; }
};
struct Derived : Base
{
void foo() { std::cout << "Derived::foo()\n"; }
};
struct Bar
{
Base* x;
Bar() : x(new Derived) {}
};
int main()
{
Bar b;
Base* Bar::*p = &Bar::x;
(b.*p)->foo();
}
You would have to static_cast to do this conversion as seen in 5.3.9/9. This reason for this is that it acts as a static_cast from parent object pointer to child object pointer would. In other words, putting a pointer to a derived member into a pointer-to-parent-member would allow you to possibly access a non-existent derived member from a parent object or pointer. If the standard allowed this automatically it would be easy to mess up and try to access a child member on a class that isn't of the appropriate child type (that contains said member).
Without more information it sounds like you need a different/better constructor/set interface in your Base class rather than trying to use pointers-to-member here.
I think what you want is a 'container', ie a struct which just has pointers:
struct Container{
Base* derivedAdata_;
Base* derivedBdata_;
...
};
Now each of the members you know to be of a specific type (ie DerivedA, DerivedB etc) so you can down-cast them later.
But first you are receiving data (in arbitrary order), but with a string name, so you should have a map:
std::map<std::string, Base* Container::*>
And you must have already populated the map:
myMap["DerivedA"] = &Container::derivedAdata;
...
Now data arrives and you start populating the container:
instance.*(myMap[key]) = factory(key, data);
myMap[key] picks the right member of the container and factory(key,data) creates instances.
btw you could just have a map as your container anyway:std::map<std::string, Base*>
Regarding the original issue, you can do this using pointer to functions, instead of introducing base classes.
class Container {
public:
void set(std::string const& label, std::string const& value);
void setName(std::string const& value) { _name = value; }
void setAge(std::string const& age) {
_age = boost::lexical_cast<size_t>(age);
}
private:
std::string _name;
size_t _age;
};
How to implement set then ?
// container.cpp
typedef void (Container::*SetterType)(std::string const&);
typedef std::map<std::string, SetterType> SettersMapType;
SettersMapType SettersMap =
boost::assign::map_list_of("name", &Container::setName)
("age", &Container::setAge);
void Container::set(std::string const& label, std::string const& value) {
SettersMapType::const_iterator it = SettersMap.find(label);
if (it == SettersMap.end()) { throw UnknownLabel(label); }
SetterType setter = it->second;
(this->*setter)(value);
}
struct Container {
Derived data_;
};
int main(void)
{
Base Container::*ptr = &Container::data_;
}
The first problem is that Container doesn't have a member called ptr
Container container_object;
Base *ptr = container_object.data_;
Would work. Note that there needs to be a container object to create the data_ member and it would need to be made public.
The alternative would be for derived::data_ to be a static member.
I'm confused with the this keyword in C++, I'm not sure that if I'm doing the right thing by passing this. Here is the piece of code that I'm struggling with:
ClassA::ClassA( ClassB &b) {
b.doSth(this);
// trying to call b's routine by passing a pointer to itself, should I use "this"?
}
ClassB::doSth(ClassA * a) {
//do sth
}
You're using it correctly. The this pointer points to the current object instance.
class helper
{
public:
void help(worker *pWorker) {
//TODO do something with pWorker . . .
}
void help2(worker& rWorker) {
//TODO do something with rWorker . . .
}
};
class worker
{
public:
void dowork() {
//this one takes a worker pointer so we can use the this pointer.
helper.help(this);
//to pass by reference, you need to dereference the this pointer.
helper.help2(*this);
}
helper helper;
};
Also, say you declare worker *pW = new worker(). If you call one of the methods (dowork) on the pW object, you will notice that the this pointer and pW have the exact same value (they are both the same address).
(haven't tested that to make sure it builds, but I think it should).
In C++, this is a keyword which is defined as "the pointer to the current object instance". So your code above is correct.
Depending on the inheritance/composition relationship between ClassA and ClassB, there are probably better ways to achieve what you are doing than by using the this pointer.
It's perfectly OK to pass 'this' or '*this' as you are doing.
Lifetime Dangers:
One point about the example you've supplied is that you're calling doSth from the constructor of ClassA. The object that's passed to doSth is possibly a partially constructed object:
class ClassC {
public:
ClassC ()
: m_c ()
{}
int m_c;
};
class ClassA : public ClassC {
public:
ClassA (ClassB & b)
: ClassC ()
, m_b ( b.doSth (this) ) // ClassC constructed
// ClassA members partially init.
{
b.doSth (this); // ClassA members initialized
}
// ...
int m_a;
};
class ClassD : public ClassA {
public:
ClassD(ClassB & b)
: ClassA (b) // Partially init
, m_d ()
{
// ClassC and ClassA constructed
// ClassD members initialized
}
int m_d;
};
There may be problems if doSth uses members that have not yet been initialized:
void ClassB::doSth (ClassA * a) {
int i = a->m_c; // OK m_c is initialized
int j = a->m_a; // Not OK, m_a not initialized when called
// from member initialization list.
int k = static_cast<ClassD*> (a).m_d; // Not OK
}
Using the dynamic type of the object:
Finally, any use of the dynamic type of the object (eg. virtual calls, dynamic_cast, typeid) will have different results on a partially constructed object than on a complete object (and in some case you can have undefined behaviour).
void ClassB::doSth (ClassA * a) {
if (ClassD * d = dynamic_cast<ClassD *> (a))
{
// Never true when called from ClassA::ClassA
}
}
In this case using this will pass a pointer to the caller class, which is A, to b.DoSth. It seems that you are doing it right. this keyword always points to the class instance that you are using it from.
this is a const pointer to its own object. this pointer is nonmodifiable.
ClassA::ClassA( ClassB &b) {
b.doSth(this);
// here 'this' refers to this object ie the instance of ClassA.
// When you pass 'this' to doSth function --> is equivalent to passing
// the instance of current object of ClassA.
//
}
If what you want is to make it the this as in thiscall, or, the actual very first parameter of any member functions (for g++), there is only one way: by the member access operators:
A* a = sth_that_give_you_an_A();
((B*)a)->doSth();
or in your case, if you want to pass the instance of class A to B::doSth.
((B*)this)->doSth();
Or, you may want to cast it to void* first to make your compiler happy.
If this is what you actually want, it is somehow the only way to do that.
However, an instance of class A may not also be an instance of class B. It is very rare that you want actually do this. You should find a proper way that allow you to down cast an instance of A to its subclass B with confidence.
Or otherwise, if you want to call B::doSth on the instance of B, it is just as normal as what you may do.
this is a pointer to the object instance, so what you are doing is correct.
Read this for more information.