A has a static function A::create() that creates an instance of A, does some initialization, and returns a pointer to it. I want to create a subclass of A and have a similar create() func:
class B : public A {
public:
static B* create();
int val;
//...
}
in this B::create() function I have to do the following:
B* B::create() {
auto b = (B*)A::create();
b -> val = 0;
//...
return b;
}
Is this the right way to do it? What will happen after the cast?
Follow-up: A has a protected/private constructor, How should I write B::create(), or B's constructor? I do want the vars inherited from A to have the same values as those created by A::create() would have
Pointer assignment between two pointers makes them point to the same pointee. So the assignment y = x; makes y point to the same pointee as x . Pointer assignment does not touch the pointees. It just changes one pointer to have the same reference as another pointer.
It is true that a pointer of one class can point to other class, but classes must be a base and derived class, then it is possible. To access the variable of the base class, base class pointer will be used.
The actual reason is - a derived class has all information about a base class and also some extra bit of information. Now a pointer to a derived class will require more space and that is not sufficient in base class. So the a pointer to a derived class cannot point to it.
Explanation: A base class pointer can point to a derived class object, but we can only access base class member or virtual functions using the base class pointer because object slicing happens when a derived class object is assigned to a base class object.
The cast won't do anything sensible unless A::create()
returns a pointer to a B
object. If A::create()
returns a pointer to an object which isn't a B
you have undefined behavior.
In C++ you deal with initialization of objects using constructors: the initialization of base classes is inherited and each derived can do whatever custom initialization it needs to do. Your B::create()
would just return a suitably constructed object:
B::B()
: A() // initialize base
, val(0) {
// other initialization
}
B* B::create() { return new B(); }
You could make class B a friend of A like this
class A {
public:
static A* createA();
int varA;
private:
friend class B; // Make B a friend so that B can use private constructor of A
A()
{
cout << "In A constructor" << endl;
varA = 5; // Initialize members of A here
}
};
A* A::createA()
{
return new A;
}
class B : public A {
public:
static B* createB();
int varB;
private:
B()
{
cout << "In B constructor" << endl;
varB = -5; // Initialize members of B here
}
};
B* B::createB()
{
return new B;
}
int main()
{
cout << "Create A" << endl;
A* x=A::createA();
cout << "x->varA is " << x->varA << endl;
cout << endl;
cout << "Create B" << endl;
B* y=B::createB();
cout << "y->varA is " << y->varA << endl;
cout << "y->varB is " << y->varB << endl;
cout << endl;
delete x;
delete y;
}
When a new B is made, the constructor of A get called automatically and the members of A will be initialized.
Output is:
Create A
In A constructor
x->varA is 5
Create B
In A constructor
In B constructor
y->varA is 5
y->varB is -5
Another way is to make the constructor of A protected instead of private.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With