Is the following safe to do? - c++

Consider this code:
struct A {};
struct B
{
B(A* a) : a(a) {}
private:
A* a;
};
struct base
{
base(B b) : b(b) {}
protected:
A a;
private:
B b;
};
struct derived : public base
{
derived() : base(B(&a)) // <-- IS THIS OK?
{}
};
Here, the base class needs a B object passed to its constructor by the derived class, and the B object refers to an A object, but the A object lives inside the base class.
The constructor of the B object does not do anything to the A pointer except store it, so I'm thinking this should be OK, but it still feels wrong because technically the A object doesn't yet exist at the time I'm passing it to the base constructor.
Can I get into trouble doing this or should this be OK?

It is safe as long as you don't use a in B's constructor, as the object a isn't constructed yet.
I mean, you shouldn't dereference the pointer a in B's constructor; however after base's constructor is executed, you can safely dereference B::a in other methods of B.

a has not been constructed, but it does have an address, and it is legal to take its address at this point. You do need to be sure, though, not to use the pointer in the constructor of B (i.e., don't dereference the pointer).
This is all rather awkward, though.

Related

Non-default constructor for C++ class which is a member of another class?

This is a question about constructors. Two C++ classes A and B are related conceptually as
class A
{
B b;
};
class B
{
A *a;
};
The question is, when an instance of A is created, I want its member B to be constructed with a pointer to A. So it seems B requires a constructor that has a pointer to an instance of A as an argument, and that that constructor of B be invoked when an instance of A is constructed, rather than the default constructor of B.
Is there a simple way to do this?
Using struct here just for the public defaults.
struct A;
struct B {
B(A *a_ptr = 0) : a(a_ptr) {}
A *a;
};
struct A {
A() : b(this) {}
B b;
};
You might get a warning in the constructor for A from a busybody compiler that this points to an object that has not been fully constructed.

Declaration vs. Instantiation

Comming from Java, I have difficulty with the code below.
In my understanding b is just declared on line 3 but not instantiated.
What would be the text book way of creating an instance of B in class A?
class A {
private:
B b;
public:
A() {
//instantiate b here?
}
};
Edit: What if B does not have a default constructor?
You could explicitly initialize b in A's constructor's initialization list, for example
class A {
B b; // private
public:
A : b() {} // the compiler provides the equivalent of this if you don't
};
However, b would get instantiated automatically anyway. The above makes sense if you need to build a B with a non-default constructor, or if B cannot be default initialized:
class A {
B b; // private
public:
A : b(someParam) {}
};
It may be impossible to correctly initialize in the constructor's initialization list, in which case an assignment can be done in the body of the constructor:
class A {
B b; // private
public:
A {
b = somethingComplicated...; // assigns new value to default constructed B.
}
};
You have created an instance of b in line 3. This line is enough so that B's constructor is called. If you have code like this
class A {
private:
B *b;
public:
A() {
//instantiate b here?
}
};
then it would make sense to instantiate b in A's constructor like
A()
{
b = new B();
}
The correct phase your looking for is "C++ initialization list". This initialization list is called/initialized before the constructor is called
In case of Default constructor, compiler equvalient constructor will be A() : B() {}
A very good reference
http://www.cprogramming.com/tutorial/initialization-lists-c++.html
At line 3, it is simply a declaration of B. However somewhere in your code where you have:
A a;
or
A a();
This calls the constructor of A. The internal b private member is full or garbage, as in not initialized. You are correct in that you can and probably should initialize member variable during construction where possible. There are two ways to do this:
A ()
{
b = B ();
}
Like you said:
or
A () : b (B())
{
}
The second version (initialization list) is slightly more efficient since it creates the new B object directly inside b. Whereas the first version creates a temporary and then moves that into b. This is the case when you initialize members from passed in parameters anyway (for non built in types). I'm making an assumption its the same in this case, but someone will be able to clarify.

How to call function from inherited class?

I have the code:
class A{ //base class
public:
virtual std::string getString(){return "class A";}
};
class B: public A{
public:
std::string getString() {return "it is B class";}
};
class C{
public:
C(){
B b;
a = b;
}
std::string test() {return a.getString();}
private:
A a;
};
int main()
{
C c;
std::cout << c.test();
return 0;
}
c.test() says "class A", but how I can call method getString() from class B and not A?
Thanks!
The problem is, your B object gets sliced when assigned to an A object. This is because you assigned by value, not by reference or pointer. Since you declared a like this
A a;
what happens during the assignment a = b is that the actual state of b is copied over into a. However, since a is a value object, only the A part of object b is copied, and its "B-ness" is completely lost!
To avoid this, you need to declare a as a pointer type, as suggested by others (a reference would also work, but then you would need to considerably rewrite your example, since you can't assign to references, only initialize them). If a is a pointer (A*), the assignment a = b makes a point to the object represented by b, which is still a B object, thus you will observe the polymorphic behaviour you expected. However, in this case, you must ensure that b stays alive even after exiting the constructor - otherwise you leave a dangling reference which causes undefined behaviour (read: bad things you don't want to happen) when dereferenced.
Since a pointer example was already shown by #Nawaz, I will give another using a reference:
class C{
public:
C() : a(b) { // references must be initialized in the constructor initializer list
}
std::string test() {return a.getString();}
private:
B b; // moved to class scope to ensure that it stays alive
A& a;
};
You need to implement like this:
class C{
public:
C(){
a = new B;
}
std::string test() {return a->getString();}
private:
A *a;
};
This will call getString() from class B and not A.
What you're trying to do is called "dynamic polymorphism" which is achieved through pointer (or reference) of type base class (which is A), but the pointer points to an object of type derived class (which is B).
Because your member a is not an A*, it is an A instance. Therefore you are just assigning the A part of B to variable a. if you convert a to an A*, you will get the expected result.
You are slicing therefore it will not work. a is an A it is not a B.
To work your class member variable a must be a pointer or a reference.
As a pointer
class C{
public:
C(){
a = new B;
}
std::string test() {return a->getString();}
private:
A *a;
};
As a reference
class C{
public:
C() : a( *(new B) )
{
}
std::string test() {return a.getString();}
private:
A &a;
};
Of course the code I have produced leaks but will work with the virtual function.

Instance of a subclass in a parent class

I have two classes in a class hierarchy where a parent class needs to have an instance of a class derived from it as a member variable. As an example:
class B;
class A {
public:
B* binst;
A();
};
class B : public A {
};
A::A() {
binst = new B;
}
Obviously, this causes an infinite recursion in the constructors, because to create a new B you have to call A's constructor, which creates a new B which calls A's constructor, and so ad infinitum.
Is there a way around this? The problem I'm having in this is that A has to have a B in it, but B must be derived from A, and there's not a way to prevent that.
To get an idea of why I need to do this, consider an object oriented hierarchy for a scripting language (like python or ruby or lua, etc):
All instances of anything are derived from a base class, Object.
Object has a method lookup table, which is an instance of MethodTable.
MethodTable is derived from Object, and must be, for the scripting language to be able to operate on it.
"Object has a method lookup table"
"MethodTable is derived from Object"
Putting aside coding concerns, do these statements really make sense together from even a conceptual standpoint? Should a MethodTable have its own MethodTable which then has its own MethodTable... etc?
I'd say it sounds like you need to refactor your concepts a bit. For instance, perhaps Object itself should somehow be responsible for exposing the necessary pieces of its MethodTable member. Thus not requiring MethodTable itself to be an Object. (There may be various other feasible designs too. It's hard to say without deeper knowledge of the actual project.)
Edit: Typically, compiler/implementation-internal types don't derive from language-dependent types. If you look at the internals of Java, their inheritance implementation won't derive from Object. Object is a language construction, it's part of your language's interface. A method table is part of the implementation. A method table should not be operated on by the language, it should be operated on by the implementation.
Moreover, enforced deriving from Object is a stupid thing to do and it happens because you didn't consider the language design and how the users were going to write generic code properly. This is especially true in dynamically typed languages like Lua or Python.
Object could have a private MethodTableImpl member and a public getter that returns a MethodTable. MethodTable contains a MethodTableImpl and derives from Object.
I don't know the purpose of your classes but here is a suggestion :
class A
{
public:
virtual void func DoIt () = 0;
...
};
class B : public virtual A
{
public:
};
class C : public virtual A ,B
{
void func DoIt () { /* statements */ }
};
now there is only 1 instance of class A.
It would be helpful to understand exactly are you trying to achieve via this construct.
As you've noted yourself, this is effectively like having A's constructor construct an instance of A, and that's an unavoidable path to stack overflow.
A more general solution would be to provide a set_subclass method for a pointer to an instance of A, which could then be populated by any subclass of A, not just B.
class A {
public:
A();
virtual ~A();
set_subclass(A* sub) { subclass = sub; }
private:
A* subclass;
};
// List(1) or Stream(2) using inheritance
struct B;
struct A {
B *inst;
A(B *inst_) : inst(inst_) {}
A() : inst(0) {}
};
struct B : A {
B(B *_inst) : A(inst) {}
// chose option 1 or 2
B() : A() {} // option 1: List
B() : A(0) {} // same as above
B() : A(this) {} // option 2: Stream
};
auto B3 = new B(new B( new B));
// This is either a length 3 list (1)
// or a stream (2) implemented by self ref 3rd element
You can make a constructor for class A which accepts a pointer to an object to class B and assign this pointer instead of allocating a new B:
A::A(B* b) : binst (b) {}
And in the construct of class B you pass 'this' in constructor of A:
B::B() : A(this) {}
The compiler will probably complain about it, but you can try. (It is ugly, though.)
Note that you can NOT use the binst pointer to access object B in A's constructor, because it's not fully constructed yet.
Does it actually need the binst as a member, or does it simply need to access it?
class B;
class A {
public:
B& binst(); //throws exception if not derived from B
A() {}
virtual ~A() {} //effectively required for the dynamic_cast
void foo();
};
class B : public A {
public:
void bar() {};
};
B& A::binst() {return dynamic_cast<B&>(this);}
void A::foo() {return binst().bar();}

Destructor order

I have a C++ class hierarchy that looks something like this:
class A;
class B
{
public:
B( A& a ) : a_( a )
{
};
private:
A& a_;
};
class MyObject
{
public:
MyObject() : b_( a_ )
{
};
private:
A a_;
B b_;
};
Occasionally, it will happen that in B's destructor I will get invalid access exceptions relating to its reference of A. It appears that A is destroyed before B.
Is there something inherently wrong with using class members to initialize other members? Is there no guarantee of the order of destruction?
Thanks,
PaulH
EDIT: I missed the MyObject part of your question so my original answer will probably not be of much help. I guess your problem lies in the code you did not post, the stripped-down example should work fine.
Class B does not “own” the object passed by reference, therefore the objects a and b have different life cycles. If the object refered to by B::a_ is destroyed, B's destructor will access an invalid reference.
Some code to explain what I mean:
class A;
class B {
public:
B(A a) : a_(a) {} // a is copied to a_
~B() { /* Access a_ */ }
private:
A a_;
};
class C {
public:
C(A& a) : a_(a) {} // a_ is a reference (implicit pointer)
// of an external object.
~C() { /* Access a_ */ }
private:
A& a_;
};
int main(int argc, char** argv) {
A* a = new A();
B b(*a);
C c(*a);
delete a;
// Now b has a valid copy of a, c has an invalid reference.
}
In the code above the destruction order is well defined.
The destruction order is the reverse of the creation order.
The creation order is the order the members were declared within the class.
So in this case:
Default Construction:
a_: constructed first using default constructor.
b_: constructed using a valid a_ passed to the constructor.
Destruction:
b_: destroyed first. The destructor can use the reference to a
As long as the object has not been copied (see below)
a_: destroyed second.
But you have a potential problem if you make a copy of the object using the copy constructor.
The following copy constructor is defined by the compiler:
MyObject::MyObject(MyObject const& copy)
:a_(copy.a_)
,b_(copy.b_)
{}
So you may have a potential problem here. As the copy will contain an object 'b_' that contains a reference that was copied from another object. If the other object is destroyed then this 'b_' will have an invalid reference.
a_ should be constructed before b_, and b_ should be destructed before a_, based on the order you have defined them in MyObject.