I have one base class and two derived child's (different classes).
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
In pseudo code this would look like this:
class Parent
{
public:
int x;
};
class ChildA : public Parent
{
void setX() {x=5;}
};
class ChildB : public Parent
{
int getX() {return x;} //Shall return 5 after calling the set method of ChildA first
};
//Creating instances
ChildA* a;
a = new ChildA();
Parent* ptrToBaseClass = a;
ChildB* b;
b = new ChildB(); //How can I set this to the same base class ptr (Parent*) which instance “a” has?
How can this be achieved with passing the base class pointer?
I would like to construct one child and then construct a second child which uses the same base class instance like the first child.
What you would like is not possible. Each base class sub object is stored within the most derived object.
You can use the existing base to copy initialise the base of another object, but they will be separate.
What you could do to achieve something similar, is to use indirection:
struct Parent
{
std::shared_ptr<int> x = std::make_shared<int>();
};
struct ChildA : Parent
{
void setX() {*x=5;}
};
struct ChildB : Parent
{
int getX() {return *x;} //Shall return 5 after calling the set method of ChildA first
};
int main() {
ChildA a;
Parent& a_base = a;
ChildB b {a_base}; // note that the base is copied here
a.setX();
std::cout << b.getX();
}
This way even though the base objects are separate, they both refer to shared state.
A simpler solution is to store the state in static storage (such as static member, as suggested by Ahmet). But this will make the state shared across all instances while the indirection allows exact control over which objects share which state.
You can make the x in Parent class static. This will allow you to do this - although I have to warn you that this is quite a dodgy code and can bite you in the a**.
Of course, then you have to access it with rather than just x; as Parent::x.
EDIT: I seem to got it wrong. If you want the whole base class as 'shared' rather than just x; you need pointers and custom logic to manage it - there is no direct language construct.
Related
I am confused by a design that I saw recently. It initialize a derived class object in the main function and pass it as a base class object into a function. Then, inside the function that object pointer is casted back to the derived class again. Is this a design pattern or should it be avoid?
Also, a member variable exclusive to the derived class is used after the pointer being converted to the base class and back to the derived class again. How would the pointer easily find the variable after the process?
class Base
{
// something
}
class Derived : public Base
{
public:
void funcDerived() {return x;}
int x = 0;
}
int process(std::shared_ptr<Base> const& var)
{
auto new_var = std::dynamic_pointer_cast<Derived>(var);
return new_var->funcDerived();
}
int main()
{
auto derived = std::make_shared<Derived>(new Derived());
derived->x = 5;
process(derived);
return 0;
}
EDIT:
To add some details of this design, the base class is an abstract class while there are several derived classes for different version. Function process() is an API whose interface remains intact. Its behavior is controlled by conditional-compilation directives.
Suppose we have an Abstract class and child (derived from abstract) classes. I know we can instantiate from derivedClass like this:
AbstractBase *foo = new DerivedClass1();
But, is this the right way to define the top line code:
AbstractBase foo = *(new DerivedClass1());
I don't want to declare the Abstract class via pointer. But, What is the best way to do this and manage the memeory leak?
Thanks a lot
AbstractBase foo = *(new DerivedClass1()); will try to construct an instance of AbstractBase (which you can't do, it's abstract) using a constructor which takes an object of type DerivedClass1 (or something it's convertible to.
If you don't want to end up with a pointer to AbstractBase, but you do want to use new to allocate the object dynamically, then you probably want:
AbstractBase& foo = *(new DerivedClass1());
to define a reference to AbstractBase from your new DerivedClass1
Here is a very simple example of how to "chain" copy constructors. Note that the syntax may be a bit off, but this is the general idea:
class ABase {
public:
ABase(const ABase& ab) {
basevar = ab.getBasevar();
}
int getBasevar() { return basevar; }
private:
int basevar;
};
class c1 : public ABase {
public:
c1(const c1& c) : ABase(c) {
cvar = c.getCvar();
}
private:
int cvar;
};
In particular, note the use of the : operator between the function declaration and definition; this space allows for multiple direct assignments in a constructor function (possibly in other functions as well) and its content is called an "initialization list". Note also this answer which details some more examples.
I am studying inheritance and polymorphism in C++ and I came across this example:
class Parent
{
public:
void a()
{
std::cout << "parentA";
}
virtual void b()
{
std::cout<<"parentB";
}
};
class Child : public Parent
{
public:
void b()
{
std::cout<<"childB";
}
};
Then in main:
int main()
{
Parent i= Child();
i.b(); //why doesn't this give parentB?
Parent *j= new Child();
j->b();
}
The outputs are parentA and childB respectively but I can't understand why. (isn't b() overriding?)
The first case should give parentB, since the object i has type Parent, not Child. The Child object is sliced - that is, its Parent subobject is copied to create i of type Parent, then the temporary Child is destroyed. You can often prevent confusing behaviour like this by making base classes abstract (that is, giving them pure virtual functions), so that they can't be instantiated.
The second case should give childB, since the object that j points to has dynamic type Child.
You have "sliced" the Child class into the Parent class. In order to access virtual methods, you need to store the instance polymorphically, like you have with your second example. Polymorphic variables are pointers and references.
Say we have two classes:
class Parent
{
public:
vector<int> x;
protected:
void Method();
}
and
class Child : public Parent
{
public:
vector<double> x;
}
and the method Method() operates on x and makes some operation, which is compatible for both types int and double:
void Parent::Method()
{
x.push_back(1);
}
Then, if I will create an instance of Child class, initialize vector<double> x, and then call derived method Method() from the base class, C++ will try to operate on Parent's member x and not the Child's one. Is there any way how to make base class method to automatically operate on the member that belongs to created class, Child's vector<int> x?
EDIT:
As McAden correctly noted, this behavior can be easily achieved using polymorphism: three classes - 1 base and 2 derived. But does it mean that it is impossible with just 2 classes?
Since you only want to create instances of Child and you want the Child to dictate the type of the vector, this problem is more naturally solved with a template Parent. As a simple example, Parent could be parameterized by what vector<> should contain:
template <typename T>
class Parent {
public:
std::vector<T> x;
protected:
void Method () { x.push_back(1); }
};
class Child : public Parent<double> {
//...
};
If you actually have many such things you want the child to control in the Parent, then you probably should treat Child more like a traits class for the Parent. Thus, Parent would actually be parameterized by its Child, and your code would then be using CRTP. which provides "static polymorphism".
template <typename CHILD>
class Parent {
protected:
void Method () {
CHILD *child = static_cast<CHILD *>(this);
child->x.push_back(1);
}
};
class Child : public Parent<Child> {
public:
std::vector<double> x;
};
Changing data types in dealing with inheritance isn't so much possible with the exception being cases where covariance is used. If you want to make a class that handles differing data types what you're probably looking for is a template class:
http://www.learncpp.com/cpp-tutorial/143-template-classes/
I can't think of a better title... please edit if you can!
class AbstractGUIBase
{
...
};
class GUIConcrete : public AbstractGUIBase
{
...
};
class AbstractApplicationBase
{
AbstractGUIBase *mGUI;
};
class MyApplication : public AbstractApplicationBase
{
GUIConcrete *mGUI;
};
This is basically the setup I have... an application base-class provides common functionality including a reference to a GUI base-class instance mGUI. mGUI is only ever instantiated in MyApplication or other concrete sub-classes.
I don't want to re-declare mGUI in both classes because I end up doing something like super::mGUI = mGUI = new ConcreteGUI(). But I also don't want to have to cast mGUI every time it's used in MyApplication.
Is there a normal patter here? I was thinking you could template AbstractApplicationBase on the GUI class type but I don't especially like template programming.
I'm using MSVC++2008 so no fancy modern stuff is available.
I'll try to strip away the details of your model and focus on the following abstract design:
struct A struct DA : A
{ {
}; };
//==============================================================================
struct B struct DB : B
{ {
A* p; DA* pD; // Avoid this
}; };
Now what you are trying to do is to avoid adding an extra member variable to DB, and be able to treat the pointer p inherited from B as if it were of type DA*.
You can structure classes B and DB this way:
struct B
{
private:
A* p;
public:
B(A* _p) : p(_p) { }
A* get_p() { return p; }
}
struct DB : B
{
public:
B(DA* _p) : B(_p) { }
DA* get_p() { return static_cast<DA*>(A::get_p()); }
}
Superclass B will hold a pointer of type A*. This pointer is set at construction time. If the constructor is invoked while creating an instance of DB, a pointer to an object of type DA will be stored. DB provides a function get_p() that hides B's version of get_p() and returns a (properly casted) pointer of type DA*.
Due to this design, the static_cast<> in DB::get_p() is guaranteed to be safe (unless you use virtual inheritance, in which case you should use the less efficient dynamic_cast<>).
Internal operations of B would access the pointer p directly. Clients of B would retrieve it through a call to B::get_p(). Inside of DB, and for clients of DB as well, you would access the object pointed to by p by retrieving the pointer through function B::get_p(), rather than directly dereferencing p.