Dependent member initialization, when reorder is not possible - c++

#include <iostream>
class BarParent
{
public:
int x;
virtual void fuz() = 0;
};
class BarChild : public BarParent
{
public:
BarChild(int new_x){x = new_x;}
virtual void fuz(){}
};
class FooParent
{
public:
BarParent* p_barPar;
FooParent (BarChild* new_p_bar)
{
p_barPar = new_p_bar;
std::cout << p_barPar->x << std::endl;
}
};
class FooChild: public FooParent
{
public:
BarChild barChild;
FooChild(int new_x):FooParent(&barChild), barChild(new_x){}
};
int main()
{
FooChild foo(60);
BarChild bar(99);
FooParent fooP(&bar);
}
Output:
-548726160
99
I understand why I am getting this result(undefined behavior), barChild is used before it is initiailized. My question is what is the 'right' to do handle this.

This is a case where design, not code needs to be fixed.
By your own design:
A BarChild must be constructed before FooParent.
A FooParent must be constructed before a FooChild.
A FooChild must be constructed before a BarChild.
When you want both FooParent and FooChild to refer to this same Bar object - as you're attempting in your code - design the parent class to manage it.
One example solution:
FooParent (BarChild* new_p_bar)
{
if ( new_p_bar == NULL )
new_p_bar = new BarChild;
p_barPar = new_p_bar;
std::cout << p_barPar->x << std::endl;
}
Here, FooChild doesn't need its own instance of this object.

Respect the order of initialization.
You can create a function inside BarParent to set the pointer p_barPar. Call the function in the constructor of FooChild.
Is there any reason you can't make barChild (in FooChild) a pointer as well?

I think you will have to find another example: this one is wrong because of the RAIII principle which is not enforced: FooParent holds a pointer on a value which it doesn't control. An interesting example of where this setup would fail is the slicing problem.

quick and dirty solution:
class FooChild: private BarChild, public FooParent
{
public:
FooChild(int new_x): BarChild(new_x), FooParent(this) {}
};

Related

How to get a reference/pointer to a class (not an object)?

I have a std::map where key is string and I want the value to be, not an object, but a reference/pointer to a class which I can instantiate.
std::map<::std::string, ?class_reference?> handlers_;
Once the specific entry is chosen, I want to create instance of the class and execute a member function.
As others have already mentioned, if you want to create relevant objects via a string (such as class name), you'll need to use factory pattern which can create related objects (same base class). Here's a simple example easy to understand (you just store lambda which returns objects in the map):
#include <map>
#include <string>
#include <functional>
#include <iostream>
class Base {};
class A : public Base{
public:
A() { std::cout << "A ctr" << std::endl; }
};
class B : public Base {
public:
B() { std::cout << "B ctr" << std::endl; }
};
int main() {
std::map<std::string, std::function<Base*()> > m;
m["a"] = []() { return new A(); };
m["b"] = []() { return new B(); };
m["a"]();
m["b"]();
}
How to get a reference/pointer to a class (not an object)?
Short answer, you can't. Unfortunately, C++ doesn't work that way.
However, to solve your specific problem, you have the option of a factory pattern, which would look something like this:
template <class T>
class factory {
public:
virtual std::unique_ptr<T> createObject() = 0;
};
class base { // some base class common to all the types you are intending to create
};
class foo : public base { // some class you want to create
};
class fooCreator : public fatory<base> {
public:
std::unique_ptr<T> createObject() {
return someUniquePointerToANewObject;
}
}
int main() {
std::map<std::string, std::unique_ptr<factory<base>>> myMap; // because we are creating some bases
myMap["some key"] = new myFooCreator;
// now let's create some new `base`
if(myMap.find("some matching key") != myMap.end()) {
std::unique_ptr<base> myBaseObject = myMap["some matching key"]->createObject();
// use created object
}
return 0;
}
Of course, there are a lot of things that could go wrong here, like if for some reason you push a nullptr to myMap. But at least you have an idea of what it looks like now.

C++ Child class inheriting parent class constructor

I have an assignment that requires two classes to be derived from a base class. I am having issues getting the derived classes to call the base class constructor and successfully set the inherited variables. I recreated the issue with a dummy program for simplicity since the assignment is much longer.
#include <iostream>
class ParentClass {
public:
ParentClass(int theField1, int junk);
ParentClass() {}
virtual void printField();
virtual void setField(int nf);
protected:
int field1;
};
class ChildClass : public ParentClass {
public:
ChildClass(int theField1);
void printField();
void setField(int nf);
};
ParentClass::ParentClass(int theField1, int junk) {
field1 = theField1;
}
ChildClass::ChildClass(int theField1) {
ParentClass::ParentClass(theField1, 3);
}
void ParentClass::printField() {
std::cout << "The field = " << field1 << std::endl;
}
void ChildClass::printField() {
ParentClass::printField();
std::cout << "Some other stuff." << std::endl;
}
void ParentClass::setField(int nf) {
field1 = nf;
}
void ChildClass::setField(int nf) {
ParentClass::setField(nf);
}
int main() {
ChildClass* myChild = new ChildClass(777);
ChildClass child2(888);
myChild->printField();
child2.printField();
myChild->setField(10);
myChild->printField();
child2.setField(20);
child2.printField();
return 0;
}
Running this gives me the following output:
The field = 0
Some other stuff.
The field = 4197296
Some other stuff.
The field = 10
Some other stuff.
The field = 20
Some other stuff.
Why do the first two attempts not work? Calling the constructor should be initializing the variables to the value passed as a parameter, but they are not actually set until I specifically call a mutator function. I tried a third class which used the parent mutator function in its constructor rather than the parent constructor:
class StepChild : public ParentClass {
public:
StepChild(int nf);
};
StepChild::StepChild(int nf) {
ParentClass::setField(nf);
}
The object as defined in main:
StepChild* step = new StepChild(30);
step->printField();
The output:
The field = 30
Where am I going wrong that attempting to use the parent constructor is not properly initializing these variables?
I also tried changing the parent class to be not virtual, and it worked as well, so it doesn't appear to be an issue with the parent class.
Use initialiser lists:
ParentClass::ParentClass(int theField1, int junk)
: field1(theField1)
{ }
ChildClass::ChildClass(int theField1)
: ParentClass(theField1, 3)
{ }
The following - from your code - creates a temporary ParentClass object and throws it away - that has no affect on the ChildClass object under construction:
ParentClass::ParentClass(theField1, 3); // temporary
If you make the parameters match, you can also do it the c++11 way by putting
using ParentClass::ParentClass( int, int );
in your ChildClass class definition. It is the same as invoking the parent constructor from the ChildClass constructor initialiser list, but a little less esoteric.
Not sure but I find something wrong in the way you are calling base class constructor.
try this way to call base class constructor and see if the problem is solved.

Polymorphic Member Variable

I got an elegant answer yesterday for my question regarding polymorphic object members.
But now I am facing the problem that the variable isn't really behaving the way I expected it to. The following code is being used:
#include <iostream>
#include <math.h>
using std::cin;
using std::cout;
using std::endl;
class Com
{
public:
virtual void setReady()
{
cout << "Com" << endl;
}
};
class DerivedCom : public Com
{
public:
void setReady()
{
cout << "DCom" << endl;
}
void somethingElse()
{
cout << "else" << endl;
}
};
class BaseClass
{
public:
Com* com;
public:
BaseClass(Com* c = new Com) : com(c)
{
}
virtual void setReady()
{
com->setReady();
}
};
class DerivedClass : public BaseClass
{
// the call to somethingElse() won't compile if I leave out this declaration
protected:
DerivedCom* com;
public:
DerivedClass() : BaseClass(new DerivedCom)
{
}
void setReady()
{
// This line causes a segfault if I put in the declaration earlier
this->com->setReady();
// This line won't compile if I leave out the declaration earlier
this->com->somethingElse();
}
};
int main()
{
DerivedClass* inst = new DerivedClass();
inst->setReady();
return 0;
}
The problem is, that DerivedClass::com is in fact of type DerivedCom but I can't access any DerivedCom-specific methods as the compiler won't find them. If I put in an extra re-declaration DerivedCom* com, the compiler will find the methods but I get segmentation faults.
Remove that extra declaration.
If you are sure that a Com* is a DerivedCom* then you can static_cast it.
static_cast<DerivedCom*>(this->com)->somethingElse();
This will likely crash it you're wrong however. So if you are not sure then you can dynamic_cast it
DerivedCom* dcom = dynamic_cast<DerivedCom*>(this->com);
if (dcom)
dcom->somethingElse();
dynamic_cast will return NULL if the object isn't of the type you asked for.
The reason for the segmentation faults is that you arent declaring the variable again with a different type, you are actually defining a new pointer in the derived class, one that is never initialized. Thus this->com->... will access the derived class com and crash since it is an uninitialized pointer.
What you are trying to do though, is to change the type of the member pointer. You could do that by making the type of the member pointer as a template variable, as follows
template <class ComType>
class BaseClassTemplate
{
ComType* com;
...;
};
typedef BaseClassTemplate<Com> BaseClass;
class DerivedClass : public BaseClassTemplate<DerivedCom>
{
...;
};
However this makes the base class a template, so to get it as you want it, you need to make an instantiation of BaseClass<Com> to get your version of base class. You can either make it a derived class or just a typedef as i have shown.

how can i move pointer of one class to another in c++

I have class named CiF and I want to move in the constructor pointer of CiF to new class named Cmanager.
I tried something like this:
CiF::CiF() : Cmanager(new Cmanager(CiF THIS))
{
}
please help
thanks
The following code shows how a pointer of one class is given to another in ctor. I think thats what you're trying to achieve.
I HIGHLY recommend you on not using code like this, but you did not give enough information about your usecase and so I'm not able to give you alternatives.
You probably should take a look into smart pointers and general class design. (When giving pointers to any other class you need to control which class owns the object, deletes it etc)
class CiF;
class Cmanager
{
public:
Cmanager() :
cif_(0)
{};
void setCiF(CiF* cif)
{
cif_ = cif;
}
private:
CiF* cif_;
};
class CiF
{
public:
CiF() :
cmanager_(Cmanager())
{
cmanager_.setCiF(this);
}
private:
Cmanager cmanager_;
};
With out having a relationship between CiF and Cmanager, I think it cannot be accomplished.
#include <iostream>
class Cmanager
{
};
class Cif:public Cmanager
{
Cmanager *ptr ;
public:
bar() : ptr(this)
{
} ;
};
int main()
{
Cif obj ;
return 0;
}

Instantiating objects and object members

For some reason the following doesn't crash like my program does, but I'm pretty sure it's similar in design. For one, the output's not correct. It outputs something similar to:
0x537ff4 5471612
While the main program outputs (nil) for the pointer address.
The key to the problem might be display_ in Drv.
Here's the code:
#include <iostream>
#include "debug.h"
class LCDText {
public:
int rows_;
LCDText() { rows_ = 10; };
};
class Generic {
LCDText *lcdText_;
public:
Generic(LCDText *lcdText) { lcdText_ = lcdText; };
void Setup() {
Error("%p %d", lcdText_, lcdText_->rows_);
}
};
class Display : public LCDText {
Generic *visitor_;
public:
Display(Generic *visitor) { visitor_ = visitor; };
};
class Drv : public Generic {
Display *display_;
public:
Drv() : Generic((LCDText *)display_) {
display_ = new Display((Generic *)this);
};
~Drv() { delete display_; };
};
int main()
{
Drv drv;
drv.Setup();
return 0;
}
This code:
Drv() : Generic((LCDText *)display_) {
display_ = new Display((Generic *)this);
};
first runs the parent class's ctor, with a yet-uninitialized value of display_, then independently sets display_, but, too late to change the parent class. So the pointer held by the parent class will never be set correctly. I guess you need to add a protected setter method (or make the parent-class-held pointer member itself protected).
Your Drv constructor passes the garbage, uninitialized value of Drv::display_ to Generic before initializing it in the constructor body. You can do a couple of things here, my preferred would be:
class Drv : public Generic {
Display* display() { return (Display*)lcdText_; }
public:
Drv() : Generic(new Display(this)) {}
}
Because it doesn't result in a duplicate field, but you can also have an abstract getLcdText() in Generic, which could be better if you are already using virtual methods.
In the constructor for Drv, when you first call the constructor for Generic display_ is still uninitialized. You don't new the pointer until later.