possible to use derived class as parameter in base class function?

In order to compile a derived class, the base class must be stated in the code previously. But in order to use the derived class as a parameter in a base class function, the derived class must have already been declared. So is there a way around this, like how we use function prototypes?

example:

1
2
3
4
5
6
7
8
9
10
class base_class
{
     public:
          void function(derived_class);
};

class derived_class: public base_class
{ 
     // whatever
};
Last edited on
on a related note, is it possible to pass the derived class as a parameter, when the function is expecting the base class (i read that this is possible in c#, not sure about c++)

example:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class base_class
{
     public:
          int x;
          void function(base_class);
} base_1;

class derived_class: public base_class
{ 
     public:
          int y;
} parameter;

int main ()
{
     // Will this work?
     parameter.function(parameter);
     // Or this?
     base_1.function(parameter);
}


and if this does work, will all the variables from the derived class be passed, or just the ones that are defined in the base class? in other words will function() have access to the passed objects' x and y, or just x?
Last edited on
1. Base needs to be defined before derived, to be used as a parent, but derived needs to be defined before base to be used in as a function argument. You could instead forward declare (class derived_class;) and then use derived_class& or * as the parameter.
Although in general base's function taking a derived argument sounds like a bad idea.

2. When you have a "will this work" question, you know, you can just try it. http://ideone.com/UqyGJ
Although it does work, it's more natural to use pointers or references, to make polymorphism work.
As for y, you certainly can't, unless you do some typecasting hackery, again with pointers or references.
ok, so if a use virtual declarations then i suppose i get function to have access to parameter's y...

like this...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class base_class
{
     public:
          int x;
          virtual void function(base_class);
} base_1;

class derived_class: public base_class
{ 
     public:
          int y;
          void function(derived_class);
} parameter;

int main ()
{
     // this will have access to both x and y passed by parameter?
     parameter.function(parameter);
     // this will have access to only x passed by parameter?
     base_1.function(parameter);
}
Firstly, void function(base_class); and void function(derived_class); are two entirely different functions, with or without virtual.
Secondly, virtual keyword is only relevant when dealing with *s or &s, because only then static type information can be misleading.

If you have a function void foo(base b) and pass my_derived to it, that derived is converted to base, loosing any information that was not in base. You can't recover that information in any way.

If you have void foo(base* b) and pass &my_derived to it, no conversion occurs. foo only thinks that it is working with a base. You still can't use members of derived though. foo must be written in such way that it works with base itself or its other children that don't have that member. It is possible, however, to check that b is in fact pointing to a derived object and cast it to derived* using dynamic_cast or some virtual function.
As Hamster says, you want pointers or references for polymorphic behavior and to avoid slicing in the case of a function taking a base class by value.

It is possible, however, to do what you originally wanted. I'm not sure how much sense it makes to do, but it is doable.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class derived_class ;
 
class base_class
{
     public:
          int x;
          void function(derived_class);
} base_1;
 
class derived_class: public base_class
{ 
     public:
          int y;
} parameter;
 
void base_class::function(derived_class) {}

int main ()
{
     // Will this work?
     parameter.function(parameter);
     // Or this?
     base_1.function(parameter);
}


As you can see, you just need to hold off on function's definition until after the compiler has seen the definition of derived_class.
Knowing that I can pass a derived object as a parameter to a function expecting a base object, even though it strips derived members, it is still suitable for my needs.

Does that also mean that I can assign a derived object to a base object using the = operator, and it will work, albeit stripping the derived members? What about in reverse? Can I assign a base object to a derived object using =, and then just have to worry about initializing the remaining derived members?

Thank you for answering all my questions. My curiosity about this topic, and polymorphism in general is peaked. I don't necessarily need the info to solve a current problem, but it seems it may be useful in the future, and it opens up options.

I wonder if using a void pointer would allow the derived object to be passed to the base function, and maintain derived members? From the chapter in the tutorial on pointers, it seems that void pointers can be used to pass generic parameters. Applying it to the code, it seems this might solve the problem:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
class base
{
     public:
          int x;
          void function(void* param, int psize);         
} base_1;

class derived: public base
{ 
     public:
          int y;
} parameter;

int main ()
{
// This should work:
    base_1.function(&parameter, sizeof(parameter));
// or:
    parameter.function(&parameter, sizeof(parameter));
//or:
    base_1.function(&base_1, sizeof(base_1));
//or:
    parameter.function(&base_1, sizeof(base_1));
}

void base::function (void* param, int psize)
{
     if ( psize == sizeof(base) )
     { 
          base* pbase; 
          pbase=(base*)param;
          // operations using only *pbase.x
     }
     else if (psize == sizeof(derived) )
     { 
          derived* pderived; 
          pderived=(derived*)param;
          // operations using both *pderived.x and *pderived.y
     }
}


Also, is there a way to do this without the sizeof() function? Perhaps by defining a string called type in the base class, and then checking against it to see what type of object the function is dealing with.
Last edited on
Does that also mean that I can assign a derived object to a base object using the = operator, and it will work, albeit stripping the derived members?


Yes.


What about in reverse? Can I assign a base object to a derived object using =, and then just have to worry about initializing the remaining derived members?


You can provide an overloaded operator= that takes a base class object (or reference to one) as a parameter in the derived class.

Avoid using void pointers in your code whenever possible. Throwing away type information is rarely a good thing.

As we've already noted, using pointers-to-base avoids slicing and enables polymorphic behavior (via virtual functions.)

Topic archived. No new replies allowed.