I am trying to write a class which holds either a pointer to an object of class A(base) or class B(derived) depending on conditions at run time.

The base class and derived class:

class A
{
protected:
	int x;
};
class B : public A
{
public:
	int y, z;
};

And a third class which holds a pointer to the base class

class C
{
public:
	C(bool derivedClass)
	{
		if (derivedClass)
		{
			pAB = new B;
		}
		else
		{
			pAB = new A;
		}
	}
	A* pAB;
	// other members
};

However, it seems that pAB is always pointing to class A(base) no matter what argument is sent to the constructor. How can I get this type of polymorphism, where I am only allocating memory for the correct class at run time?

Recommended Answers

All 10 Replies

Class C is derived from class A, so creating an object of type C will automatically create an internal object of A. Object of type C contains an object of type A

Class C is derived from class A, so creating an object of type C will automatically create an internal object of A. Object of type C contains an object of type A

Correction: class B is derived from class A, so creating an object of type B will automatically create an internal object of A. Object of type C contains a pointer to object of type A

:confused:
I know gerard "mis-spoke", but is this supposed to be an extension to your question or am I missing something here? Did gerard answer your question sufficiently?

you could use a void pointer(ofc you'll have to add more interface to your class to eliminate error prone as void pointers are very dangerous)

Correction: class B is derived from class A, so creating an object of type B will automatically create an internal object of A. Object of type C contains a pointer to object of type A

Yes, thank-you for the correction.

:confused:
I know gerard "mis-spoke", but is this supposed to be an extension to your question or am I missing something here? Did gerard answer your question sufficiently?

No. My question is this: How can I write a class C which contains a pointer to either an object of class A or of class B (derived from A) depending on conditions at run time.

The gerard answer is a summary of the three class that appear at the top of the thread, but they do not work the way I intended.

Thank you.

Do you mean something like below?

#include <iostream>

class A
{
public:
  virtual void display_it() const { std::cout << "class A" << std::endl; }
protected:
	int x;
};
class B : public A
{
public:
  void display_it() const { std::cout << "class B" << std::endl; }
	int y, z;
};

class C
{
public:
	C(bool derivedClass)
	{
		if (derivedClass)
		{
			pAB = new B;
		}
		else
		{
			pAB = new A;
		}
	}
	
	void whoami() const { pAB->display_it(); }
	
	A* pAB;
	// other members
};

int main(int argc, char**argv)
{
  C one(true);
  C two(false);
  
  one.whoami();//class B
  two.whoami();//class A
  
  return 0;
}
commented: Thank you. Well explained. +3

It's really not a good use of them, but you could do it with templates:

template <typename T>
class C {
 private:
   T* myPtr;
 public:
   C () : myPtr(NULL) {}
   C (T *incoming) : myPtr(incoming) {}
   //...
};

class A {
  //...
};

class B : public A {
  //...
};

This type of class construction would allow you to do something like the following:

int main() {
  char kind = '\0';

  std::cout << "What kind? ";
  std::cin >> kind;

  switch (kind) {
    case 'A':
      C<A> Cobject(new A);
      break;
    case 'B':
      C<B> Cobject(new B);
      break;
    //...
  }

  //...

}

Notice the syntax used when declaring "Cobject" and how it changes depending on what you're looking for.

There is one caveat though. Because B is derived from A, it contains all of the public and protected members of the A class. If you use a template in this way, you will not have access to the members of the A class because your pointer is pointing directly at the B object instead of at the embedded A object.

To access the A interface from a B object, you would have to add "wrapper" members to the B class that resolve the scope of the A class for you, which is a lot of extra work.

It would be possible to add a proper polymorphic element to this by creating another case, perhaps called 'P':

switch (kind) {
    case 'A':
      C<A> Cobject(new A);
      break;
    case 'B':
      C<B> Cobject(new B);
      break;
    case 'P':              //new "polymorphic" case
      C<A> Cobject(new B);
      break;
    //...
  }
commented: Excellent! +3

Re: Gerard...

Yes, thank you. Is it possible to access the members int y,z of class B? Or would I need a pointer of class B to do that?

Re: Gerard...

Yes, thank you. Is it possible to access the members int y,z of class B? Or would I need a pointer of class B to do that?

If your object is created like

A * pAB = new B;

Then yes you can access members y and z.

If your object is created like

A * pAB = new A;

Then you can't access members y and z because they don't exist.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.