Very weird problems involving pointer member variables and polymorphism - c++

Okay, so I'm experiencing some very weird issues with storing an array of base class pointers in a class then settings this base class pointers equal to some dynamically allocated derived class pointers.
My code is too long and bloated with GUI calls to post here, so I'll make some mock code here that demonstrates the methodology I'm using
Base Class - Base
class Base
{
public:
Base(){ // do nothing}
virtual void SetUI(){ // do nothing}
}
Derived Class - Derived
class Derived : public Base
{
public:
Derived() : Base() { // do nothing}
virtual void SetUI(){// do nothing}
}
This is a class that basically holds data for my program, it contains an array of pointers to the base class. These pointers are initialized by having them point to dynamically created objects of the derived class type.
class HelperClass
{
private:
Base * basearray[2];
public:
HelperClass()
{
basearray[0] = new Derived;
basearray[1] = new Derived;
}
Base * getBaseArray(int key)
{
return this->basearray[key];
}
}
here is my "main", this is where everything starts getting weird.
int main()
{
HelperClass hold;
hold.getBaseArray(0)->setUI();
// NOTHING HAPPENS ABOVE, THE CODE DOESN'T EVEN REACH THIS POINT, IT JUST GET'S LOST SOMEWHERE IN //THE ABOVE STATEMENT. i KNOW THIS BECAUSE I PUT AN exit(0) inside the function setUI() for both the //base and derived class and the program doesn't exit.
// this also does nothing
if(hold->getBaseArray(0) || !hold->getBaseArray(0))
exit(0);
return 0;
}
but oddly enough, if i do something like the following, where I just declare a base class pointer and have it point to a dynamically created object of the derived class, everything works just fine.
int main()
{
Base *hold;
hold = new Derived;
hold->setUI(); // <- this works polymorphically
return 0;
}
Does anyone have any idea why my program stops working when I try to work with the array of base class pointers inside the HelperClass? When I try to do getBaseArray(int) it doesn't return anything, which causes statements like
if(hold->getBaseArray(0) || !hold->getBaseArray(0)) {exit(0);}
to not make the program exit, which is weird because the pointer that getBaseArray() returns is either null or non-null, which means the program should exit no matter what

I (and my compiler) found two mistackes you have in the first main()
You declare SetUI() in your Base and Derived class, but in the main you try to call setUI(). Perhaps you have both functions in your project and that's why you recieved nothing.
You declare hold as an object and not a pointer. With this you can not do like hold->someFn(). You should call thet like hold.someFn().
Here is the code with corrections. It runs by me without problems. Try it.
struct Base
{
Base(){}
virtual ~Base() {}
virtual void SetUI() {
cout << "base" << endl;
}
};
struct Derived : public Base
{
Derived() : Base() {}
virtual ~Derived() {}
virtual void SetUI() {
cout << "derived" << endl;
}
};
class HelperClass
{
Base * basearray[2];
public:
HelperClass() {
basearray[0] = new Derived;
basearray[1] = new Derived;
}
~HelperClass() {
delete basearray[0];
delete basearray[1];
}
Base *getBaseArray(int key) {
return basearray[key];
}
};
int main()
{
HelperClass hold;
hold.getBaseArray(0)->SetUI();
if(hold.getBaseArray(0))
cout << "some output" << endl;
return 0;
}

Related

DerivedA pointer pointing to DerivedB

I have a base class which serves as an interface (if I use that word correctly). The idea is that the base class has some derived classes that implement one virtual function of the base class. Then I also need another class that extends the base class (lets call it extended base). What I would like is that I can store a class derived from base into an extended base pointer.
MWE:
class Base {
public:
virtual ~Base();
virtual double value();
}
class Derived : public Base{
public:
double value() override {return 5;}
}
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase ();
virtual double value2(){return 10;}
}
int main() {
ExtendedBase * object;
object = new Derived();
std::cout << object->value(); //should give implementation in Derived, i.e. 5
std::cout << object->value2(); //should give implementation in ExtendedBase, i.e. 10
delete object;
return 0;
}
With this MWE I get a compile error at the second line in the main. error: cannot convert 'Derived*' to 'ExtendedBase*' in assignment object = new Derived();. Part of me understands why it doesn't work (although I can't explain), but I would like to know if I can get the desired behaviour in some other way.
P.S. Sorry about the bad question name, I couldn't think of another way to keep it short
P.S.2 I know raw pointers like this are not advised. In the future I will change to smart pointers but I don't think they are needed for this simple example
ExtendedBase and Derived are each derived from Base. If you want to use an ExtendedBase* pointer to point to a Derived object, you will need to derive Derived from ExtendedBase.
To use a different example,
class Feline{
virtual void run();
}
class Housecat : Feline{
void run() {}
}
class BigCat : Feline{
virtual void run();
virtual void roar();
}
Here Feline, Housecat, and BigCat are analogous to Base, Derived, and ExtendedBase. BigCat and Housecat are each Feline, but since Housecat is not a BigCat, you can't use a BigCat* pointer to point to a Housecat.
This is the desired behavior from a language architect perspective.
For instance, if you have
class Ship
{
public:
virtual void move() = 0;
}
class Steamboat : public Ship
{
public:
virtual void move() override { ... }
}
class Sailboat : public Ship
{
public:
virtual void move() override { ... }
virtual void setSails() { ... }
}
Now, you don't want a Steamboat to become a Sailboat all of a sudden, hence:
Steamboat* tootoo = new Sailboat;
cannot be valid.
That's why your code cannot work. Conceptually.
So giving a quick fix is not possible, because your concept is not really clear.
When you are assigning an address to a pointer that means you should be able to access all the members of the type the pointer is pointing to through the pointer.
For ex,
class B {};
class D : B {};
B *p = new D();
now through p, at least you can access all the members of base portion of the derived class.
But in your code,
ExtendedBase * object;
object = new Derived();
object should be able to access all the members of ExtendedBase portion of the derived class. But how is it possible as derived class is not derived from ExtendeBase. So compiler is throwing error.
You need to do some changes in your code to work.
To make base as interface (abstract class), you need to define at
least one member function as pure virtual.
If you want to access the member function of ExtendedBase through
Base pointer, you should define same function 'val' in your
ExtendedBase.
Below are the changes.
#include <iostream>
using namespace std;
class Base {
public:
virtual ~Base() {};
virtual double value() = 0;
};
class Derived : public Base{
public:
~Derived() {};
double value() {
return 5;
}
};
class ExtendedBase : public Base {
public:
virtual ~ExtendedBase () {};
double value()
{
return 10;
}
};
int main() {
Base *p = new Derived();
std::cout << p->value() << std::endl;
delete p;
Base *p1 = new ExtendedBase();
std::cout << p1->value() << std::endl;
delete p1;
return 0;
}

Unusual behavior with C++ vectors

struct Base{
int hp = 1000;
virtual ~Base()
{
std::cout << "Base destructor\n";
}
};
struct Child : Base {
int hp = 100;
virtual ~Child()
{
std::cout << "Child destructor\n";
}
};
int main()
{
std::vector<Base*>vct;
for(int x=0;x<25;x++)
{
vct.push_back(new Child);
}
std::cout << vct[3]->hp;
return 0;
}
I have written this program, which creates 25 objects of type Child, yet when run, both the destructors of the child and base class are called, which would imply that the 'new child' call would create an instance of both the child, and the base class. Why?
Furthermore, trying to access the int "hp" of any of the members of the vector, always returns 1000, not 100, which indicates that all the vector members are of type Base, not of type Child.
So in short, what do I need to do to 1. only create Child objects, not Base(even having the Base class as an abstract class still, somehow, seems to create objects of it) 2. Have all the members/elements of the vector to be of the child class, when the type of the vector is Base*
This is exactly how C++ inheritance works. Even if you didn't explicitly define a constructor, the parent class's default constructor still runs. In this case, the default constructors are mostly a no-op save for the member initialization of hp in both.
Both Child destructor and Base destructor get printed because you declared your destructor (correctly) as virtual. However, you aren't explicitly deleting any instance of objects you are allocating via new, so I'm not sure how you are seeing any print statements at all.
The hp in Child shadows the hp in Base, but member variables are not virtual. So when you access hp via Base class pointer, you get the Base class member. If you want to have the derived class access to hp, mark hp as protected in Base, and set in constructor in derived. In you case, everything is a struct, so all members are already public.
struct Base{
int hp = 1000;
virtual ~Base()
{
std::cout << "Base destructor\n";
}
};
struct Child : Base {
Child()
{
hp = 100; // Base constructor has already run, so we override here
}
virtual ~Child()
{
std::cout << "Child destructor\n";
}
};
int main()
{
std::vector<Base*>vct;
for(int x=0;x<25;x++)
{
vct.push_back(new Child);
}
std::cout << vct[3]->hp;
// let's delete explicitly and avoid the leak.
for(int x=0;x<25;x++)
{
delete vec[x];
vec[x] = nullptr; // not necessary, but is a good practice
}
return 0;
}

Is this a memory leak of deleting base class pointer, and how to make it right

Does the following case has memory leak? I suppose in foo(), the delete *e only sees the base part of the object. What about *e = NULL, is this refers to the Base object as well?
Sorry to mention, I used gcc4.4.7.
What is the good way of doing it? Any suggestion is appreciate!
class Base
{
public:
Base() {}
virtual ~Base() {}
virtual bool valid() { return true; }
}
class Derived : public Base
{
public:
Derived() {}
~Derived() {}
bool valid() { return false; }
}
void foo(Base** e)
{
if((*e)->valid() {
cout << "is valid";
}
else{
cout<< " not valid";
delete *e;
*e = NULL;
}
}
int main()
{
Derived* d = new Derived;
Base* cast_d = static_cast<Base*>(d);
foo(&cast_d);
}
That is not at all a memory leak. When we delete a base class pointer if the base class pointer is holding the address of a derive class object it will first call derived class destructor if that is declared virtual. That is the reason why we have virtual destructor but not virtual constructor in C++. If we are using a Base class pointer to store the address of various derived classes pointers we should always declare the derived class destructor as virtual so that memory release should done in correct order.
Hope this will help you.
In the code there is no memory leak
the virtual destructor, allows any derived class to be properly destroyed.
If a Base * was passed into foo, it would not get destroyed, so it may leak . But that is not in the code presented.

Creating derived class instance using base class instance

I have a base class instance, there is a derived class that inherits from the base class, I want to transform the base instance into derived instance, (if possible without copying anything (maybe sending to the derived class a reference of the base class)) how can I achieve that?
Note: I need this because I'm using factory design pattern which identify the derived class needed to be created using a parameter located in the base instance.
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Thanks.
Consider the case of the car.
You can treat a Lamborghini as a car.
You can treat a Yugo as a car.
You can treat a car as a Lamborghini if it is a Lamborghini. In C++ this means a pointer to car that really points to a Lamborghini. In order to get a Lamborghini pointer back out of the car pointer you should use dynamic_cast. If the car does not point to a Lamborghini, dynamic_cast will return NULL. This keeps you from trying to pass off a Yugo as a Lamborghini and blowing the Yugo's engine.
But when the Lamborghini is being treated as a car, it can only do car things. If you copy a Lamborghini into a car, you strip out all Lamborghini-ness forever. It's gone.
Code time!
This, I'm afraid cannot be done:
//class A
//class B: public A (pure virtual)
//class C: public B
B BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
C is being copied into a B and the B is being returned. B would need a constructor that took a C, but the point is moot. B cannot be instantiated if it's pure virtual. For now we'll ignore the leak that would be new C()
Also can't use a reference for this job, pretty much the same problem, so you're trapped into returning a pointer
B * BFactory::makeB(A &a) {
int n=a.getN();
if(n==1){
return new C();
}
}
Now I'm going to make a suggestion: Build the make function into B and handle the case where A doesn't map to anything recognized by B.
class B: public A
{
public:
virtual ~B(){}
static B * makeB(A & a)
{
switch(a.getN())
{
case 1:
return new C();
}
return NULL;
}
};
But this leads to another recommendation: Why should B know anything? And What is the point of A at this level? Why is A storing build codes for classes two or more steps down the hierarchy? Bad from a maintenance point of view. The point of objects is they know who they are and how to manipulate themselves. Short-circuiting this leads to pain.
class B: public A
{
public:
virtual ~B(){}
virtual B* makeB() = 0;
};
Now B only makes Bs, needs no help from A, and those who extend B are stuck with figuring out how to make themselves--a task they should know better than anyone else. Much safer because there is never any possibility of a code unrecognised by B for a new class.
class C: public B
{
public:
B* makeB()
{
return new C();
}
};
class D: public B
{
public:
B* makeB()
{
return new D();
}
};
Edit: Traditional factory
You're asking for an abstract factory. For that you need nothing. You don't even need a class. You certainly don't need a class A. The goal of this sort of factory is the caller knows nothing about the class. By providing an A, the caller needs to know how to make an A or have another factory that makes an A.
First a bit of set-up in a header file BFactory.h:
#ifndef BFACTORY_H_
#define BFACTORY_H_
#include <exception>
class B
{
public:
virtual ~B(){}
virtual std::string whatAmI() = 0;
protected:
// data members common to all B subclasses
};
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
B* BFactory(enum bType type);
#endif /* BFACTORY_H_ */
Here I'm going to deviate from the book way a little. Rather than using an integer to identify the type to be built, I'm going to use an enum. Two reasons: Easier to read and understand gimme_a_C than 1 and generates a compiler error if you try to provide a value that is not enumerated.
enum bType
{
gimmie_a_C,
gimmie_a_D,
gimmie_an_E
};
And an exception to flag stupidity if the enum is updated with new types (gimmie_an_E) but the factory is not.
class BadTypeException: public std::exception
{
public:
const char* what() const noexcept
{
return "Dude! WTF?!?";
}
};
This is all the Factory client needs to see. They don't see C. They don't see D. They have no clue that C and D exist in any way other than the names listed in enum bType. All they ever see is pointers to B.
Now for the implementation BFactory.cpp:
#include "BFactory.h"
class C:public B
{
std::string whatAmI()
{
return "C";
}
};
class D:public B
{
std::string whatAmI()
{
return "D";
}
};
B* BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return new C();
case gimmie_a_D:
return new C();
default:
throw BadTypeException();
}
}
I'll leave it up to the reader to spot the stupid bug in the above code that makes these error prone and why I don't like them.
And usage, main.cpp:
#include "BFactory.h"
int main()
{
B * temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
delete temp;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
delete temp;
//temp = BFactory(1001); // won't compile
try
{
temp = BFactory(gimmie_an_E); // will compile, throws exception
std::cout << temp->whatAmI() << std::endl;
}
catch(BadTypeException& wtf)
{
std::cerr << wtf.what() << std::endl;
}
}
There is still absolutely no use for or involvement of A. A if it exists, should no nothing about B or the children of B.
These days there is a little improvement we can make so that the pointers are a little safer. unique_ptr allows us to maintain the polymporphic advantages of a pointer to B without the memory management woes.
std::unique_ptr<B> BFactory(enum bType type)
{
switch(type)
{
case gimmie_a_C:
return std::unique_ptr<B>(new C());
case gimmie_a_D:
return std::unique_ptr<B>(new D());
default:
throw BadTypeException();
}
}
and the new main:
int main()
{
std::unique_ptr<B> temp;
temp = BFactory(gimmie_a_C);
std::cout << temp->whatAmI() << std::endl;
temp = BFactory(gimmie_a_D);
std::cout << temp->whatAmI() << std::endl;
}
You might want to define a constructor that takes the base class instance as the argument so you can later use static_cast to convert from the base class to the derived class.
class Derived : public Base
{
public:
Derived(const Base& base) : Base{base} {}
};
int main()
{
Base a;
Derived b = static_cast<Derived>(a);
}
If you want to create a derived class instance using the base class instance then there is some conversion rule between the two, which you can specify explicitly using a derived class constructor.
Although it is impossible to alter the type of an object you still can make instances of base and derived classes share the same data:
#include <memory>
#include <iostream>
class Base
{
protected:
struct CommonData
{
int A;
int B;
};
std::shared_ptr<CommonData> m_data;
public:
Base() : m_data(std::make_shared<CommonData>())
{
m_data->A = 0;
m_data->B = 0;
}
void SetData(Base * source)
{
m_data = source->m_data;
}
int A() const { return m_data->A; }
int B() const { return m_data->B; }
void SetA(int value) { m_data->A = value; }
void SetB(int value) { m_data->B = value; }
};
class Derived : public Base
{
public:
int C;
};
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
Base base;
base.SetA(12);
base.SetB(46);
Derived derived;
derived.SetData(&base);
derived.C = 555;
cout << derived.A() << endl; // 12
cout << derived.C << endl; // 555;
cin.get();
}
A base class should not "know" about how to make its own derived class instances. That is the point of inheritance.
The "is a" relationship of derived classes means that any subclass instance will pass as a base class instance transparently, and you can treat it as one, and by default base class non-virtual methods are called on a base class reference, even if it a derived class instance. Only virtual methods use the derived class method.
In the case of creating a base class instance from a derived class you want to "slice" the instance data (normally a bad thing and normally a mistake).
class A{ // ... A stuff };
class B : A
{ // ... B stuff
A make_A() { return (A) B(*this); } // copy cast to A
};
Under no circumstances try to do this:
class B;
class A { // ...
B make_B() { return B(*this); }
};
That is inverted OO logic. It requires at least 2 scans of the source code, which C++ does not do. It fails.

Calling a subclass method. Pointer vs non-pointer

I have the following code:
main.hxx:
#include <iostream>
class Base{
public:
Base() {}
~Base() {}
virtual void whoAreYou() { std::cout << "I am base!" << std::endl;}
};
class Sub : public Base{
public:
Sub() {}
~Sub() {}
virtual void whoAreYou() { std::cout << "I am Sub!" << std::endl;}
};
class Factory {
public:
static Base getBase() { return Base(); }
static Base* getBasePtr() { return new Base(); }
static Base getSub() { return Sub(); }
static Base* getSubPtr() { return new Sub(); }
};
main.cxx
#include "main.hxx"
int main (int argc, char **argv) {
// Non pointers
Factory::getBase().whoAreYou();
Factory::getSub().whoAreYou();
// Pointers
Base* basePtr = Factory::getBasePtr();
Base* subPtr = Factory::getSubPtr();
basePtr->whoAreYou();
subPtr->whoAreYou();
delete basePtr, subPtr;
return 0;
}
When run, it prints the following:
I am base!
I am base!
I am base!
I am Sub!
I was expecting "Factory::getSub().whoAreYou();" to print "I am Sub!". Is it because when not using a pointer it gets casted to a Base?
I was expecting Factory::getSub().whoAreYou(); to print "I am Sub!".
No, the function returns a Base, so a Base is what you get.
Is it because when not using a pointer it gets casted to a Base?
Yes (although the word is "converted" not "casted" - a cast is an explicit conversion, and this conversion is implicit). This is sometimes called "slicing", since the derived-class part of the object is "sliced off" when it's copied.
Also, beware that the following:
delete basePtr, subPtr;
only deletes subPtr. You need a separate delete expression for each. You also need a virtual destructor in Base to safely delete subPtr.
This line creates a Sub then call Base default copy constructor to create a instance of Base from a the instance Sub:
static Base getSub() { return Sub(); }
Hence your log.
More generaly a Base is a Base instance, whereas Base* is a pointer on a Base instance or an object that inherits Base.