Pass subclasses to a function that takes their superclass - c++

Let's say I have three classes - Animal, Cat and Dog, where Cat and Dog are subclasses of Animal (this does sound like the first lectures, but it's not homework I promise, just simplifying the real code)
Dog* spike = new Dog();
Cat* puss = new Cat();
int main(int argc, char** argv)
{
function(spike, puss);
return 0;
}
void function(Animal *pet, Animal *pet2)
{
magic->andSoForth();
}
Now this generates the following error:
Cannot convert parameter 1 from 'Dog *' to 'Animal'
No constructor could take the source type,
or constructor overload resolution was ambiguous
Changing the parameters to exactly match generates similar errors, only that it says it can't convert from a class to the same class.
I have successfully called the subclasses functions and members that they inherit from the superclass, so I know that this, logically, should work. I just don't know in what twisted way this language want me to bend logic.
EDIT
Solution happen to be: pointers confuse everyone.
Declare pointers.
Send pointers as arguments to a function that does NOT handle pointers.
In my example, I sent the "not-pointers" to the function that wanted pointers, I just switched that. Now it works fine.

When you dynamically allocate a new object, you get a pointer to that object. So you need to store it in a pointer like so:
Dog* spike = new Dog();
Cat* puss = new Cat();
You can then pass spike or puss for any parameter of type Animal*, assuming Dog and Cat do indeed inherit from Animal. This is the basics of polymorphism in C++:
A prvalue of type “pointer to cv D”, where D is a class type, can be converted to a prvalue of type “pointer to cv B”, where B is a base class (Clause 10) of D.
You could, of course, have stored them right away as Animal*:
Animal* spike = new Dog();
Animal* puss = new Cat();
Don't forget to delete them. Better yet, don't use new at all:
Dog spike;
Cat puss;
void function(const Animal&, const Animal&);
function(spike, puss);

It's reasonable to assume that the problem you have is assigning a pointer to a non-pointer, or vice versa. But your code is not the real code, and your error messages are apparently not the real error messages. So it's all guesswork, in particular those already-posted answers that say "this is it" (it probably is, but not necessarily, and the uncertainty is entirely your own fault).
EDIT: the OP changed the question's code 10 seconds after I posted this.
The code still does not square with the purported error message.
I'm not going to chase this question as it changes.
Now, as to what to do…
Don't use new.
Experienced C++ programmers sometimes use new in controlled ways, wrapped in suitable code. Incompetent C++ programmers often use new as a matter of course. But in general, you don't need it, and it's problematic, so better as default don't use it.
Then, your program (which you neglected to show) would look like this:
#include <iostream>
struct Animal {};
struct Dog: Animal {};
struct Cat: Animal {};
void function(Animal const& pet1, Animal const& pet2 )
{
//magicAndSoForth();
}
int main()
{
Dog spike;
Cat puss;
function( spike, puss );
}

Your prototype for function almost certainly says
void function(Animal pet1, Animal pet2);
or something very similar to that. (I know you have a prototype, since function appears after main. If you hadn't forward-declared it, C++ would complain that it couldn't find function at all, not that it's taking the wrong types of args.)
Problem is, your real function takes pointers. And since main appears before the real function, it doesn't see that. It only sees a declaration of one that takes actual Animals, so it tries to use that...but fails, because an Animal pointer is not an Animal. (The real function differing from the prototype is fine with C++, due to the possibility of overloading. As far as the compiler knows, function(Animal, Animal) exists in another translation unit, and you're just defining function(Animal*, Animal*) too.)
Look through your code for the declaration of function, and make it say
void function(Animal *pet1, Animal *pet2);
to match up with the actual function's signature.
PS: this would have been so much easier to figure out if you had included all the relevant declarations.
PPS: A better idea would be to take references instead, as suggested by Alf. But in order to do that anyway, you'd have to fix the prototype mismatch (or make the real function appear before code that uses it) first

Well, what you need to do is this
Animal *spike = new Dog();
Animal *puss = new Cat();
Basically, all your pointer definitions must be of the base class, and these may be initialized with derived class pointers.

This is how it should look.
Dog* spike = new Dog();
Cat* puss = new Cat();
function(*spike, *puss);
void function(Animal pet, Animal pet2)
{
//magic
}
Tested and working.

Related

dynamic cast with inheritance hierarchies

so I have this code:
Base* objbase = new Derived();
//perform a downcast at runtime with dynamic_cast
Derived* objDer = dynamic_cast<Derived*>(objBase);
if(objDer)//check for success of the cast
objDer->CallDerivedFunction();
This is a snippet of code for a cast operators section in my book.
Now why do I have this, I don't understand what's the point of having to dynamically cast a pointer to a base object pointing to a Derived object; For me, that's something to do with polymorphism giving us the ability to do objBase->DeriveClassFunction(), but I don't really know.
In the first place why does it do this: Base* objbase = new Derived();, and then why does it cast a base object pointer to a Derived again, I can't quite figure out why.
Thanks in advance.
That code snippet is just a demonstration of what's possible. It describes a tool, what you do with this tool is up to you. A slightly bigger example might be:
class Animal {
void Feed();
};
class Cat : public Animal { /*...*/ };
class Dog : public Animal {
// Only dogs need to go out for a walk
void WalkTheDog();
};
void Noon(Animal* pet)
{
// No matter what our pet is, we should feed it
pet->Feed();
// If our pet is a dog, we should also take it out at noon
Dog* dog = dynamic_cast<Dog*>(pet);
if(dog) // Check if the cast succeeded
dog->WalkTheDog();
}
Noon(new Cat()); // Feed the cat
Noon(new Dog()); // Feed the dog and take him out
Notice that every animal has the Feed() function, but only dogs have the WalkTheDog() function, so in order to call that function, we need to have a pointer to a dog. But it would also be quite a waste to copy the Noon() function for both types, especially if we might later add even more animals. So instead, the Noon() function works for any kind of animal, and does only the dog-specific things only if the animal is actually a dog.

C++ Casting From Parent to Child After Passing as a Function?

I was wondering if this (above title) is exactly possible when it comes to inheriting from an interface within C++.
class Animal
{
public:
virtual void Eat(Animal& a) = 0; //Function that attempts to eat an animal.
}
class Dog : Animal
{
public:
void Eat(Animal& a);
}
void Dog::Eat(Animal& a)
{
Dog d = (Dog) a;
// Do something.
}
int main()
{
Dog dog1 = Dog();
Dog dog2 = Dog();
dog1.Eat(dog2);
return;
}
So basically, I know that the animal that my dog is going to be eating is only other dogs (in all cases ever, not just in this specific example). However, I am inheriting from a purely virtual class Animal which requires me to define the function with the Animal parameter.
I know that having a parameter as Animal causes the function Dog::Eat to think that the parameter is an Animal and not a Dog. However, considering that the data for the object to be represented as a Dog is still there I am pretty sure that there is a way to establish (cast, etc) the Animal as a Dog, I just don't know how and I am not quite sure how to search.
So I am wondering how I would do this. I am pretty sure that you can use a dynamic cast or a reinterpret cast, but I am under the impression that you typically want to minimize the use of these casts if you can. I am pretty new to Object Oriented within C++ since I used to mainly use only C.
You can indeed cast it (assuming you intended Dog to be derived publicly from Animal); but you would have to cast a reference or pointer. Your cast to a value would try to create a new Dog from the Animal that was passed in; and there is no suitable conversion for that.
// safest, if you can't guarantee the type
Dog & d = dynamic_cast<Dog&>(a); // throws if wrong type
Dog * d = dynamic_cast<Dog*>(&a); // gives null if wrong type
// fastest, if you can guarantee the type
Dog & d = static_cast<Dog&>(a); // goes horribly wrong if wrong type
Don't use reinterpret_cast; that allows all sorts of crazy conversions, so it's easy to do something wrong. Don't use the C-style cast (Dog&)a either - that allows even more conversions than reinterpret_cast, and has a syntax that's subtle and difficult to search for.
In general, you shouldn't need a cast at all - try to design the base class so that it exposes everything you want to do with it, with no need to know the actual object type.

Why C++ allow converting pointer to base object into pointer of derived class [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Downcasting using the Static_cast in C++
I'm very confused by when do we need to convert pointer to base object into pointer of derived class?
Can anyone do me a favor to give me some example?
What kind of conversion are you talking about?
If it's about down casting (or dynamic casting, which is the same kind but it's verified at runtime) then you are allowed to do it to force the type checker to not check that specific type by enforcing the one you are specifying.
This means that it is a potential break inside your code, the guaranteed type safety is missing in that specific instruction but sometimes it is needed, even if a good design should never need it a priori.
The necessity is given by the fact that without the cast you wouldn't be allowed to call any method of the derived class even if you are sure that the pointer to the base one contains a derived one (but the compiler can't verify it).
WHEN
so heres an example:
say you have a factory (an animal factory) that you can send it a string or an enum of what type of object you want...
"Hey Animal Factory, give me a 'Dog'"
there are two ways to write your factory...
You could write a function for every animal like so (good programmers dont do this):
Dog* GetDog();
Cat* GetCat();
Etc
or you could write a factory with one function like so (dont think about generics for now):
Animal* GetAnimal(string animalType);
You know that Animal is actually a dog or cat so you can typecast it to what you need it to be WHEN you need to access the members of Dog or Cat...
My Favorite thing to do in C++ is the temporary cast to get into something
(excuse my C++ its rusty)
Animal* myAnimal = Factory.GetAnimal("Dog");
int barkVolume = ((Dog*)myAnimal).BarkVolume;
Imagine you have a base class Animal and two derived classes, Cat and Dog.
// Assume methods are public.
class Animal { virtual void Attack(); }
class Dog : public Animal { void Meow(); }
class Cat : public Animal { void Bark(); }
We can use base class pointers to reference our derived objects. This helps as we can now contain them as the same type.
Animal* myCat = new Cat;
Animal* myDog = newDog;
std::vector<Animal*> myAnimals;
myAnimals.push_back(myCat);
myAnimals.push_back(myDog);
This is useful, as we can call base member functions all all kinds of animals, regardless of their derived class types.
// Call Attack() on every cat and dog.
for_each(myAnimals.begin(), myAnimals.end(), [](auto& e) { e->Attack(); });
You can use dynamic casting to test if one of the base pointers can be converted into a derived class pointer.
Cat* realCat = dynamic_cast<Cat*> myAnimals[0]; // Success. Pointer is valid.
Cat* fakeCat = dynamic_cast<Cat*> myAnimals[1]; // Failure, it's not a cat. NULL.
You can now call your member methods, such as Meow() from the derived class pointers. This was not possible before, as Animal does not have these methods.
realCat->Meow(); // Valid.
myCat->Meow(); // Animal*, there is not Meow() method.
You would need to do this to access members of the derived class that don't exist in the base class. With good programming practices and generics, you probably shouldn't have pointers typed as the base class anyway, though.

What's the principle of type casting?

Quoted from here:
CMediaType mymt;
AM_MEDIA_TYPE pmt = (AM_MEDIA_TYPE*)&mymt;
Why can a CMediaType object be cast to AM_MEDIA_TYPE?
Is such feature available in c?
UPDATE
Can someone answer it seriously what's the principle behind cast subclasses to their base classes, can I do it the other way around?
UPDATE2
AM_MEDIA_TYPE/CMediaType casting
GetMediaType(4, &m_mt);
HRESULT GetMediaType(int iPosition, CMediaType *pmt)
{
...
HRESULT STDMETHODCALLTYPE SetFormat(AM_MEDIA_TYPE *pmt)
{
m_mt = *pmt;
...
In this particular case, CMediaType extends AM_MEDIA_TYPE directly, so the cast will work just fine. (You're talking about the DirectShow classes, are you?) You can always cast subclasses to their base classes safely, that's why it'll work.
Here's a simple class structure with inheritance:
public class Animal {
public abstract String makeSound();
public void move(...) {
...
}
}
public class Lion extends Animal {
public String makeSound() {
return "GRRRRRR";
}
public void yawn() {
...
}
}
You could instantiate a lion like this and then cast it to an Animal safely:
Lion lion = new Lion();
Animal animal = (Animal) lion; //Perfectly legal
animal.move();
animal.makeSound();
By extending Animal (or inheriting from Animal, as it's also called), the Lion class states that it is also an animal (they have a is-a-relationship), therefore, it's safe to cast a lion to an animal and assume it has all the properties and methods defined in the Animal class.
Casting a base class to a subclass, however, will not usually work:
Animal animal = getAnimalFromSomeWhere();
Lion lion = (Lion) animal;
lion.yawn();
This can't work, as not every animal is a lion. Depending on the language, you'll either get type cast errors or just undefined behaviour at runtime.
There's an exception: If you know for certain the object you have is of a particular subclass, you can do the cast anyway. So in if animal in fact is a Lion, this'll work just fine:
Animal animal = getAnimalFromSomeWhere();
Lion lion = (Lion) animal; //works if animal is lion, fails otherwise
lion.yawn();
Most languages offer type checks at runtime ("Is this animal a lion?"), I don't know how that would look in C++, though, so another Java-ish example:
if (animal instanceof Lion) {
Lion lion = (Lion) animal; //safe
}
Upcasting (from sub to base) is commonly done when you want to access a set of derived instances in a uniform way (for example, you are building a list of Animal instances, but you have instances of Lion, Cow and Cat). If you need to access the instances just through the Animal interface, there's no problem. You can call Animal methods on upcasted instances.
The opposite happens when all you get is a bunch of Animal instances, but you have to operate only on the subset of them having a particular type. This is called downcasting, I read a general tendency to frown upon it, but in some cases it just works. You perform a safe downcasting with dynamic_cast. If the object is not of the instance you request, it returns null (if you are working with pointers, otherwise it raises an exception).
In C you don't have classes. With casting, you just tell the compiler to reinterpret the contents of the byte array you have in memory. I've seen it done a lot in GTK.
This is an example in C. IMPORTANT: this is ugly C. My C is rustier than a 1870 truck and I am in a hurry. There's plenty of don'ts in this code.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct a {
int an_int;
char a_string[8];
char another_string[16];
char a_third_string[16];
};
struct b {
int an_int;
char first_four[4];
char last_four[4];
};
int main() {
struct a *a_ptr=NULL;
struct b *b_ptr=NULL;
a_ptr = malloc(sizeof(struct a));
bzero(a_ptr, sizeof(struct a));
a_ptr->an_int =10;
strncpy(a_ptr->a_string,"hello", 8);
a_ptr->a_string[strlen("hello")] = 0;
strncpy(a_ptr->another_string,"hello2", 16);
a_ptr->another_string[strlen("hello2")] = 0;
strncpy(a_ptr->a_third_string,"hello3", 16);
a_ptr->a_third_string[strlen("hello3")] = 0;
b_ptr = (struct b *)a_ptr;
printf("%n\n", b_ptr->an_int);
printf("%s\n", b_ptr->last_four);
}
When you cast to struct b *, you overlay the memory area you previously referred with a_ptr with the new "vision" through b. Via b, you cannot access another_string nor a_third_string.
C has no concept of inheritance, it has no base and sub classes.
This concept exist only in C++ and most other object oriented languages like C# or Java.
The principle is simple. If you have a class Dog and Cat which both derive from Mammal.
If Dog and Cat are subclasses of Mammal, thus they are always Mammals, and therefore can alway be cast into a Mammal.
The other way around is not so simple. If you cast a Cat to a Mammal you can then later cast is back into Cat. But you cannot cast it to Dog, because it is still a Cat, although you may have stored it into a variable of type Mammal by casting it.
You're asking about two different features: upcasting and typecasting. The two are distinct in C++, since you don't need typecasting to upcast. Upcasting is when you treat an instance of a descendent class as an instance of a base class; the principle behind this is the Liskov substitution principle. Typecasting involves reinterpreting the type or converting between types in C++. There are different kinds of typecasting in C++, each with different typecasting operators (static_cast, dynamic_cast, reinterpret_cast, const_cast, C-style cast). Typecasting allows for more general substitutions, and doesn't so much follow a principle as violate them, which is why C and C++ programs that use casting aren't type safe.
Why can a CMediaType object be cast to AM_MEDIA_TYPE?
This is a design decision. You can't cast everything to everything else, and you definitely don't want to. Also, while you can cast objects from base-to-derived or derived-to-base, you can cast between unrelated classes if the classes define conversion operators.
I suspect that the sample code creates a CMediaType object to take advantage of RAII. But the function called doesn't take a CMediaType, so the object is cast to an AM_MEDIA_TYPE.
Is such feature available in c?
There are casts in C, but the system is different. There is no way to define conversion operators, and there is no language concept of base or derived classes. You can write functions that take objects of one type and return objects of another. You may be interested in the GTK+ object model, which is implemented in C.
what's the principle behind cast[ing] subclasses to their base classes, can I do it the other way around?
The sample code uses a C-style cast. I highly discourage that in C++ code. static_cast, dynamic_cast, const_cast and reinterpret_cast all do different things, and it is very useful to distinguish between them.
Since there are no type hierarchies in C there is no downcasting or upcasting.
So, answering your question for C++: casting from a derived to a base class is always safe. You don't even have to write the cast:
// BTW, prefer smart pointers like boost::scoped_ptr
Derived* foo = new Derived();
Base* bar = foo;
// or you could write simply "Base* bar = new Derived()"
Casting back is not necessarily safe, so you must write the cast and dynamic_cast was created so you know if the cast actually succeeded:
Base* foo = new Derived();
Derived* bar = dynamic_cast<Derived*>(foo);
if (bar == NULL) {
// foo didn't point to a Derived or something derived from Derived
return;
}
// foo DID point to a Derived or something derived from Derived, access it through bar
...
Again, C doesn't have anything like dynamic_cast because C doesn't have type hierarchies. You can use a C-style cast, but there is no way for a C-style cast to report "sorry, there is no way to cast between those objects." You want to know when objects aren't related, and for that you need to use dynamic_cast.

Base class pointer vs inherited class pointer?

Suppose I have a class Dog that inherits from a class Animal. What is the difference between these two lines of code?
Animal *a = new Dog();
Dog *d = new Dog();
In one, the pointer is for the base class, and in the other, the pointer is for the derived class. But when would this distinction become important? For polymorphism, either one would work exactly the same, right?
For all purposes of type-checking, the compiler treats a as if it could point to any Animal, even though you know it points to a Dog:
You can't pass a to a function expecting a Dog*.
You can't do a->fetchStick(), where fetchStick is a member function of Dog but not Animal.
Dog *d2 = dynamic_cast<Dog*>(d) is probably just a pointer copy on your compiler. Dog *d3 = dynamic_cast<Dog*>(a) probably isn't (I'm speculating here, I'm not going to bother checking on any compiler. The point is: the compiler likely makes different assumptions about a and d when transforming code).
etc.
You can call virtual functions (that is, the defined polymorphic interface) of Animal equally through either of them, with the same effect. Assuming Dog hasn't hidden them, anyway (good point, JaredPar).
For non-virtual functions which are defined in Animal, and also defined (overloaded) in Dog, calling that function via a is different from calling it via d.
The answer to this question is a giant: It depends
There are numerous ways in which the type of the pointer could become important. C++ is a very complex language and one of the ways it shows up is with inheritance.
Lets take a short example to demonstrate one of the many ways in which this could matter.
class Animal {
public:
virtual void MakeSound(const char* pNoise) { ... }
virtual void MakeSound() { ... }
};
class Dog : public Animal {
public:
virtual void MakeSound() {... }
};
int main() {
Animal* a = new Dog();
Dog* d = new Dog();
a->MakeSound("bark");
d->MakeSound("bark"); // Does not compile
return 0;
}
The reason why is a quirk of the way C++ does name lookup. In Short: When looking for a method to call C++ will walk the type hierarchy looking for the first type which has a method of the matching name. It will then look for a correct overload from the methods with that name declared on that type. Since Dog only declares a MakeSound method with no parameters, no overload matches and it fails to compile.
The first line allow you to call only members of the Animal class on a :
Animal *a = new Dog();
a->eat(); // assuming all Animal can eat(), here we will call Dog::eat() implementation.
a->bark(); // COMPILATION ERROR : bark() is not a member of Animal! Even if it's available in Dog, here we manipulate an Animal.
Although (as pointed by others), in this cas as a is still an Animal, you can't provide a as a parameter of a function asking for a more specific child class that is Dog :
void toy( Dog* dog );
toy( a ); // COMPILATION ERROR : we want a Dog!
The second line allow you to use specific functions of the child class :
Dog *a = new Dog();
a->bark(); // works, but only because we're manipulating a Dog
So use the base class as the "generic" interface of your class hierarchy (allowing you to make all your Animals to eat() whithout bothering about how).
The distinction is important when you call a virtual function using the pointer. Let's say Animal and Dog both have functions called do_stuff().
If Animal::do_stuff() is declared virtual, calling do_stuff() on an Animal pointer will call Dog::do_stuff().
If Animal::do_stuff() is not declared virtual, calling do_stuff() on an Animal pointer will call Animal::do_stuff().
Here's a full working program to demonstrate:
#include <iostream>
class Animal {
public:
void do_stuff() { std::cout << "Animal::do_stuff\n"; }
virtual void virt_stuff() { std::cout << "Animal::virt_stuff\n"; }
};
class Dog : public Animal {
public:
void do_stuff() { std::cout << "Dog::do_stuff\n"; }
void virt_stuff() { std::cout << "Dog::virt_stuff\n"; }
};
int main(int argc, char *argv[])
{
Animal *a = new Dog();
Dog *b = new Dog();
a->do_stuff();
b->do_stuff();
a->virt_stuff();
b->virt_stuff();
}
Output:
Animal::do_stuff
Dog::do_stuff
Dog::virt_stuff
Dog::virt_stuff
This is just one example. The other answers list other important differences.
No, they aren't the same.
The Dog pointer is not as polymorphic as Animal. All it can point to at runtime is a Dog or a subclass of Dog. If there are no subclasses of Dog, then the Dog runtime type and compile time types are the same.
The Animal pointer can refer to any subclass of Animal: Dog, Cat, Wildebeast, etc.
The difference is important when you try to call Dog's methods that are not Animal's method. In the first case (pointer to Animal) you have to cast the pointer to Dog first. Another difference is if you happen to overload non-virtual method. Then either Animal::non_virtual_method() (pointer to Animal) or Dog::non_virtual_method(pointer to Dog) will be called.
You must always remember there are 2 parts in every class, the data and the interface.
Your code truly created 2 Dog objects on the heap. Which means the data is of Dog.
This object is of size the sum of all data members Dog + Animal + the vtable pointer.
The ponters a and d (lvalues) differ as from a interface point of view. Which determines how you can treat them code wise. So even though Animal* a is really a Dog, you could not access a->Bark() even if Dog::Bark() existed. d->Bark() would have worked fine.
Adding the vtable back into the picture, assuming the interface of Animal had Animal::Move a generic Move() and that Dog really overwriten with a Dog::Move() { like a dog }.
Even if you had Animal a* and performed a->Move() thanks to the vtable you would actually Move() { like a dog }. This happens because Animal::Move() was a (virtual) function pointer re-pointed to Dog's::Move() while constructing Dog().
It makes no real difference at run time, as the two instances are the same. The only difference is at compile time, where you could call for example d->bark() but not a->bark(), even if a actually contains a dog. The compiler considers the variable to be an animal and only that.