I was trying to create a member (prop of class A) to a class (B). This member "prop" of class A needs to gets the "this" pointer of the newly created B-instance passed in its constructor. Just as shown in the snippet (Snippet 1) below.
However, this is failing at compile time with the error message:
"A typespecifier was expected" (translated from german).
I think this is about I am not able to use the this-pointer in this context, but I do not want to go the way of Snippet 2 and use a pointer. It is just not practical for me.
Is there any way to accomplish this close to the coding style of the first snippet?
Snippet 1
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
A prop(this);
};
Snippet 2
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
B()
{
this->prop = new A(this);
}
A* prop;
};
Edit: Just figured out this snippet, but when having many of them in one class makes it really unreadable.
Snippet 3
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
B() : prop(this) {};
A prop;
};
Many thanks!
Sebastian
You cannot initialize class member in class declaration. As you correctly noted in snippet #3 - constructor initialization list exists for the members, that require parameters to be passed to constructor.
Using an initializtion list is the best way IMHO of doing this, note, members are initialized in the order you declare them, but not the order at initializer list:
class B
{
public:
B() : prop(this) {};
A prop;
};
I got the solution by myself now.
For non-experimental; non-c++11 standard, luri Covalisin is right.
But if we give a look at c++11, we can do as follows:
class B;
class A
{
public:
A(B* b)
{
// ...
};
};
class B
{
public:
A prop{this};
};
this looks kinda weird, but is more like what I was looking for.
Related
Suppose:
class A
{
public:
A *Parent;
};
class B : public A
{
protected:
B *BParent;
};
but both 'Parent' and 'BParent' in A and B need to occupy the same memory space !
The BParent in B 'is' in fact an A, but for all B objects the parent always is a B as well, and it makes it easier to access B-only functions and variables, without the need to cast Parent to B all the time in all B and from B inheriting classes and without the need to have everything virtualized in A that may be needed in B.
Is this possible ?
Following obviously doesn't work, but is there something similar that does work ?
class B : public A
{
protected:
union {
A::Parent ;
B *BParent;
};
};
I'd rather avoid:
class A
{
public:
union {
A *Parent ;
class B *BParent ;
};
};
which would work. I would use this latter method if there is a way to make BParent private in A and still access it in B, so that it's hidden to all non-B objects that inherit from A.
Not entirely sure what you're asking for but here's a go.
I'm guessing you want to save some sort of access to the parent which is inherited but works for the derived types.. Maybe you're looking for this:
template <class T>
class A
{
private:
T *parent;
};
class B : public A<B>
{
};
But it also seems like you want to preserve that A and the B...
So maybe what you're really looking for is this:
class A
{
protected:
A *AParent() { return parent; }
protected:
A *parent;
};
class B : public A
{
protected:
B *BParent() { return (B*)parent; };
};
Note that if you want to use the same memory for both then they must be the same. Simply casting the pointers should do what you want.
I have the following structures:
class ElementEx
{
public:
ElementEx() {}
AddChild(ElementEx* element)
{
// some stuff
}
};
class A : ElementEx
{
public:
A() {}
};
class B : ElementEx
{
public:
B() {}
};
template <class T>
class MyNewClass : public T
{
public:
MyNewClass()
{
ElementEx* newElement = new ElementEx();
AddChild(newElement);
}
};
When creating a MyNewClass object, T must inherit from A or B, so MyNewClass will descend from ElementEx. But in my example, the compiler doesn't know this, and can't figure out what AddChild is. How do I make sure the T class is a descendant of ElementEx?
I'm imagining doing
((ElementEx*)this)->AddChild(newElement);
But that seems really inelegant (and prone to error, if the wrong type is fed in as T), and I figure there must be a better way to do this.
The compiler is complaining here because it doesn't know that AddChild is dependent on T during the first pass. AddChild can be made a dependent name by prepending the call with this-> hence delaying the lookup to the second pass when T is known.
As long as you're content that the parent class supports AddChild accepting an ElementEx you can do this easily using the normal compiler error.
After fixing a bunch of errors in your code (A and B inherit privately, all your classes have private constructors, AddChild has no return type) I was able to make it work fine by adding this-> to the call to AddChild because AddChild is a dependent name and you indicate that to the compiler by either qualifying the type or by adding this->. If you don't anticipate the need for virtual calls to that method you could altenately call ElementEx::AddChild to force the correct lookup. Corrected code follows.
class ElementEx
{
public:
ElementEx() {}
void AddChild(ElementEx* element)
{
// some stuff
}
};
class A : public ElementEx
{
public:
A() {}
};
class B : public ElementEx
{
public:
B() {}
};
template <class T>
class MyNewClass : public T
{
public:
MyNewClass()
{
ElementEx* newElement = new ElementEx();
this->AddChild(newElement);
}
};
struct Bad {};
int main()
{
MyNewClass<B> b; // Compiles.
MyNewClass<Bad> bad; // error: 'class MyNewClass<Bad>' has no member named 'AddChild'
}
There are a few ways to do this nicely, but they all have the basis of using 1.) static assert. 2) Static eval functions.
Personaly, I'd use (in the constructor)
static_assert(std::is_base_of<ElementEx,T>::value,"T must derive from ElementEx")
But there is probably a better way. What is the X part of your problem (what are you trying to achieve with this weird inheritance structure?)
I have a class..
class myClass
{
public:
myClass(int time);
}
Then I need to have this class within struct.
class TopClass
{
public:
typedef struct{
int myint;
myClass myclass;
}tStruct;
tStruct sStruct1;
tStruct sStruct2;
}
How can I do it? How can I call constructors for myClass?
Is only way to use class instead of struct?
My constructor
TopClass::TopClass():
sStruct1({32, myClass(100)}),
sStruct2({52, myClass(1000)})
{
}
But I am getting error:
extended initializer lists only available with -std=c++0x or -std=gnu++0x
You can add constructor to struct: http://ideone.com/ifBw2
class TopClass
{
public:
struct tStruct {
tStruct(int time, int k = 0): myint(k), myclass(time) {}
int myint;
myClass myclass;
};
TopClass(int t): sStruct1(t), sStruct2(t) {}
tStruct sStruct1;
tStruct sStruct2;
};
Edit
As for new question - you have to use new standard (-std=c++0x) to do that this way. In old standard you have to add explicit ctor to initialize member variables. struct in C++ is nearly exactly the same as class - you can add ctors, member functions, static functions. The only difference is default privacy - public for struct and private for class:
class A {
public:
int b;
};
is exactly the same as
struct A {
int b;
};
How can I do it? How can I call constructors for myClass?
Your struct will need a constructor, since it has a member with no default constructor. In order to have a constructor, it will also need its own name, not just a typedef alias.
struct tStruct {
// If you want a default constructor:
tStruct() : myClass(42) {}
// If you want to specify the time:
tStruct(int time) : myClass(time) {}
int myint;
myClass myclass;
};
Is only way to use class instead of struct?
class and struct mean exactly the same thing (apart from the minor distinction of having different default access specifiers). Anything you can do with one, you can do with the other.
Actually, Pawel Zubrycki’s answer is all right.
But I want to know why you have to do in this way that you have to import another class constructor inside TopClass.
I mean that the code should follow the rule of high cohesion and low coupling.
In software construction we’d rather prefer the composition (an important design mode) to a class defination in it. Something like the following code.
class B{
public:
B(int y){b = y;}
private:
int b;
};
class A {
public:
A(int x):b(x){...};
private:
B b;
};
From the code we can maximize class B and obviously reduce the complexity of class A. A & B can change all by themselves.
here is the thing, I want to (probably not the best thing to do) have the ability to call some class constructor that receives as a parameter a pointer to the class who's calling (ufff!!!). Well in code looks better, here it goes, as I do it in C#.
public class SomeClass
{
SomeOtherClass someOtherClass;
//Constructor
public SomeClass(SomeOtherClass someOtherClass)
{
this->someOtherClass = someOtherClass;
}
}
public class SomeOtherClass
{
public SomeOtherMethod()
{
SomeClass c = new SomeClass(this);
}
}
So, How can I achieve the same result in c++?
Thanx in advance.
class SomeOtherClass; // forward declaration (needed when used class is not visible)
class SomeClass
{
SomeOtherClass *someOtherClass;
public:
SomeClass(SomeOtherClass *some) : someOtherClass(some)
{} // this is called initialization at constructor (not assignment)
}
class SomeOtherClass
{
public:
SomeOtherMethod()
{
SomeClass *c = new SomeClass(this);
}
}
Having answered your requirements above, also note that in C++ you really don't need to declare objects always with new. If you declare,
SomeOtherClass someOtherClass;
then it means that you have an object of SomeOtherClass named someOtherClass.
probably not the best thing to do
It might not be a bad idea. However, every time you use pointers in C++, you must be completely clear about how it will be used: what kind of thing is being pointed to (not just the type of the pointer, but scalar vs. array, etc.), how the pointed-at thing gets there (e.g. via new? As part of some other object? Something else?), and how it will all get cleaned up.
How can I achieve the same result in c++?
Almost identically, except of course that C++ does not use new when you create a local instance by value (so we instead write SomeClass c = SomeClass(this);, or more simply SomeClass c(this);), and we must be aware of the pointer vs. value types (so SomeClass::someOtherClass is now a SomeOtherClass *, which is also the type we accept in the constructor). You should also strongly consider using initialization lists to initialize data members, thus SomeClass::SomeClass(SomeOtherClass* someOtherClass): someOtherClass(someOtherClass) {}.
You can do pretty much the same thing in C++ as well:
class B;
class A
{
public:
A (B * b) : pb (b) { }
private:
B * pb;
};
class B
{
public:
B () : a (this) { }
private:
A a;
};
The question is, do you really need that?
Maybe like this :)
class SomeOtherClass;
class SomeClass
{
private:
SomeOtherClass * someOtherClass;
public:
SomeClass(SomeOtherClass *someOtherClass)
{
someOtherClass = someOtherClass;
}
};
class SomeOtherClass
{
public:
void SomeOtherMethod()
{
SomeClass *c = new SomeClass(this);
}
};
'this' is a pointer-to-const in member functions (methods) declared as const.
So:
void f1(X* p);
void f2(const X* p);
class X {
void m1() {
f1(this); // OK
f2(this); // also OK
}
void m2() const {
f2(this); // OK
f1(this); // error, 'this' is a pointer to const X
}
};
Is there anyway to declare an object of a class before the class is created in C++? I ask because I am trying to use two classes, the first needs to have an instance of the second class within it, but the second class also contains an instance of the first class. I realize that you may think I might get into an infinite loop, but I actually need to create and instance of the second class before the first class.
You can't do something like this:
class A {
B b;
};
class B {
A a;
};
The most obvious problem is the compiler doesn't know how to large it needs to make class A, because the size of B depends on the size of A!
You can, however, do this:
class B; // this is a "forward declaration"
class A {
B *b;
};
class B {
A a;
};
Declaring class B as a forward declaration allows you to use pointers (and references) to that class without yet having the whole class definition.
You can't declare an instance of an undefined class but you can declare a pointer to one:
class A; // Declare that we have a class A without defining it yet.
class B
{
public:
A *itemA;
};
class A
{
public:
B *itemB;
};
There's an elegant solution using templates.
template< int T > class BaseTemplate {};
typedef BaseTemplate< 0 > A;
typedef BaseTemplate< 1 > B;
// A
template<> class BaseTemplate< 0 >
{
public:
BaseTemplate() {} // A constructor
B getB();
}
// B
template<> class BaseTemplate< 1 >
{
public:
BaseTemplate() {} // B constructor
A getA();
}
inline B A::getB() { return A(); }
inline A B::getA() { return B(); }
This code will work! So, why does it
work? The reason has to do with how
templates are compiled. Templates
delay the creation of function
signatures until you actually use the
template somewhere. This means that
neither getA() nor getB() will have
their signatures analyzed until after
both classes A and B have already been
fully declared. That's the magic of
this method.
Is this close to what you want: The first class contains the second class, but the second class (that is to be created first) just has a reference to the first class?
This is called cross reference. See here an example.