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.
Related
Hello everyone and thanks for reading,
I'm new to working with classes and I've ran into an issues with making array's of objects,
I have a base class, and an array of the same type, I'd like to know if it's a possibility to
make subclasses of the base class type and put them into an array and call methods that're not
in the base class, sorry if this is a bad question and my apologies if my wording is off,
#include <iostream>
int main()
{
BaseClass* ObjectList[10];
ObjectList[0] = new SubClass;
ObjectList[0]->Load(10);
ObjectList[0]->OtherFunction(); // How Can I Do This?
return 0;
}
class BaseClass
{
public:
virtual void Load(int Num) = 0;
};
class SubClass : public BaseClass
{
void Load(int Num) override
{
std::cout << Num << std::flush;
}
void OtherFunction()
{
// Do Something
}
};
Thanks
Edit -
My intent is to have a simple base class with dozens and dozens of subclasses with different methods, and have an array of the base class,
You can always have more than one pointer (or reference) to the same object.
int main()
{
BaseClass* ObjectList[10];
SubClass TheSubclass;
ObjectList[0] = &TheSubclass;
ObjectList[0]->Load(10); // presumably in a loop
TheSubclass.OtherFunction();
return 0;
}
You will have to downcast your pointer to the real class (or at least a class having the method). You can use either a static_cast if you do not need any control, or a dynamic_cast if you want a run-time validation of the cast:
...
SubClass *psc = dynamic_cast<SubClass *>(ObjectList[0]);
if (psc != nullptr) { // an invalid cast would set it to NULL
psc->OtherFunction();
}
else {
// process the error
}
class MainClass
{
string _ClassName;
public:
string MainClass(string _C)
{
_ClassName = _C;
}
SubClass s1;
};
class SubClass : public MainClass
{
public:
string Method_1()
{
return a;
}
string Method_2()
{
return a;
}
};
Why is SubClass s1 not working can someone tell me please what am i missing I'm new to OOP.
I want to instantiate SubClass object inside MainClass but it doesn't seems to work.
basically, my aim is to access SubClass functions when MainClass object is instantiated in Main method something like this:
int Main()
{
MainClass M1("test");
M1.s1.Method_1(); <--------- this
}
The first problem is, that the MainClass does not know a thing about SubClass when you're trying to instantiate the object.
You need to use a forward declaration and a pointer to make it work.
Header file:
class SubClass; //Forward declaration, allows pointer.
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
~MainClass();
SubClass *s1; //Size: 4 Bytes on 32bit system
protected:
MainClass();
};
class SubClass : public MainClass
{
public:
string Method_1();
string Method_2();
};
CPP file:
#include "headerFile.h"
MainClass::MainClass(string _C) :
_ClassName(_C),
s1(new SubClass) //Class definition is now known.
{
}
MainClass::MainClass() : s1(nullptr) //Nullptr -> No new object, no infinite recursion.
{
}
MainClass::~MainClass()
{
delete s1; //Do not forget to clean up your pointer.
}
string SubClass::Method_1()
{
return "a";
}
string SubClass::Method_2()
{
return "a";
}
Call:
int main()
{
MainClass M1("test");
M1.s1->Method_1(); //-> to dereference the pointer.
}
The second problem, as Richard Critten has pointed out, is an infinite recursion, which will cause your program to crash very quickly.
Each time you instantiate a SubClass, you also create a subclass, which creates yet another MainClass etc.
To circumvent this, you'll need a protected constructor, which does NOT create the subclass member.
The third problem:
You are returning a in your methods, which suggests a variable.
If you meant to return 'a', you need to put them into quotation marks.
Finally, in order to get it to compile, you'll need to write Main with a small m (int main()), otherwise the linker will complain.
However, as Mr. 'Not a number' correctly stated, the above edits only make your code compile.
What you likely are actually after however would be using virtual functions, which can be overridden by sub classes to specialize the behavior.
An example code using actual inheritance:
Header file:
class MainClass
{
string _ClassName;
public:
MainClass(string _C); //No return type on constructor
virtual ~MainClass(); //All base classes that have at least one virtual method should also have a virtual destructor, even if it is empty.
virtual void doSomething();
};
class SubClass : public MainClass
{
public:
SubClass(string className);
void doSomething();
};
CPP file:
#include "headerFile.h"
#include <stdio.h>
MainClass::MainClass(string _C) : _ClassName(_C)
{
}
MainClass::~MainClass()
{}
void MainClass::doSomething()
{
printf("Called from MainClass\n");
}
SubClass::SubClass(string className) : MainClass(className)
{
}
void SubClass::doSomething()
{
printf("Called from SubClass\n");
}
Call:
int main()
{
MainClass M1("test");
SubClass sub("SubClass");
MainClass *pointer = ⊂
M1.doSomething(); //Outputs 'Called from MainClass'.
sub.doSomething(); //Outputs 'Called from SubClass'.
pointer->doSomething(); //Also outputs 'Called from SubClass', since it points to sub and because sub overrides the behaviour from MainClass.
}
To call the parent method from the child method, you need to invoke the method from within the override with the parent class.
Example (in SubClass::doSomething): MainClass::doSomething().
Is it possible to create an instance of a class on a heap without calling default constructor and with a valid vtable for inheritance? Let me demonstrate what I will like to do:
class A
{
protected: virtual void _fake_static_method()
{
}
};
class B1 : public A
{
protected: virtual void _fake_static_method()
{
std::cout << "Hello";
}
public: static void run_fake_static_method()
{
B1* dummy = static_cast<B1*>(::operator new(sizeof(B1)));
dummy->_fake_static_method();
free(dummy);
}
}
class B2 : public A
{
public: static void run_fake_static_method()
{
B2* dummy = static_cast<B2*>(::operator new(sizeof(B2)));
dummy->_fake_static_method();
free(dummy);
}
}
Here I want to call a static method from example B1::run_fake_static_method(). In that method I want to run a member method, but I don't want to call the default constructor. I need such an implementation to remove the virtual method without a compiling error among other errors. Like a "virtual static method" I hope you understand what I want to do.
Is there a special trick that I can get this to work? :)
#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) {}
};
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.