How to cast an abstract object as an object of a derived class?

Pages: 12
So I have a vector of abstract clas objects and I'm trying to cast a specific element as an object of a derived class, but I'm not sure how. Here's some pseudocode to show:
1
2
std::vector<Abstract> objects;
Derived(objects[0]).doSomething();
However, in the second line, I get the Intellisense error
IntelliSense: no instance of constructor "Derived::Derived" matches the argument list
argument types are: (Abstract) c:\Users\jordan\Documents\Visual Studio 2012\Projects\SS + RA + CD\SS + RA + CD\Engine.cpp

So, I'm guessing I make a copy constructor, but this is my first time dealing with those so how exactly do I make a copy constructor that allows me to cast an Abstract object as that Derived class?
You have to make a copy constructor, that's right.
But the syntax tells you everything.

I'll cut it down for you.
Derived in your case is a class which is derived from Abstract, right?
The type of objects[0] is ... Abstract, right?

So, replacing objects[0] with it's type you call this Method:
Derived(Abstract) {}

Since you won't change the passed object you might think: "meh, do I have to use pass by value?" No!
A feature of C++ in a case like this is that you can pass by reference if the Object isn't changed. We do that by declaring the object const.
Derived(const Abstract&) {}

So there you have it. You may use and of those two Methods depending on your needs.

Usually you also have a copy constructor in your abstract class.
If you don't have one written yourself the compiler might create it for you.
So your ConversionConstructor in Derived should look like this:
Derived(const Abstract& a) : Abstract(a) {}

I hope that helps you! :D

Edit 1.0: here a short example
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
#include <iostream>

class Base
{
public:
    Base() {} // Note: You have to implement the default constructor if any 
    Base(const Base& base) { *this = base; }
    void make() { std::cout << "make base" << std::endl; }
};
class Derived : public Base
{
public:
    Derived() {} // Note: You have to implement the default constructor if any other is declared
    Derived(const Base& base) : Base(base) {}
    void make() { std::cout << "make derived" << std::endl; }
};

int main(void)
{
    Base base;
    base.make(); // make base

    Derived derived;
    derived.make(); // make derived

    Base(derived).make(); // make base
    Derived(base).make(); // make derived

    ((Base)derived).make(); // make base
    ((Derived)base).make(); // make derived

    return 0;
}


Edit 2.0:
Here is an example using Polymorphism.
Note that you don't need the conversion constructor here
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
#include <iostream>

class A
{
public:
    void make() { std::cout << "make a" << std::endl; }
    virtual void make2() { std::cout << "make virtual a" << std::endl; }
};

class B : public A
{
public:
    void make() { std::cout << "make b" << std::endl; }
    virtual void make2() { std::cout << "make virtual b" << std::endl; }
};

int main(void)
{
    A* a = new A;
    a->make(); // make a

    B* b = new B;
    b->make(); // make b

    delete a;
    a = b;
    a->make(); // make a 
    a->make2(); // make virtual b 
    static_cast<B*>(a)->make(); // make b

    static_cast<A*>(b)->make(); // make a

    return 0;
}
Last edited on
You need to use pointers if you want to utilize polymorphism. Also, you can only implicitly cast pointers of derived classes to pointers of base classes, not the other way around. You can cast "back down", so to speak, to the specific derived class, but you need to make sure that the pointer you have does actually refer to the correct type of derived class.

http://www.cplusplus.com/doc/tutorial/polymorphism/
http://en.cppreference.com/w/cpp/language/dynamic_cast

An example:
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
class Base
{
    ...
};

class DerivedOne : public Base
{
    ...
};

class DerivedTwo : public Base
{
    ...
};

int main()
{
    vector<Base*> objects;
    objects.push_back(new DerivedOne());
    objects.push_back(new DerivedTwo());

    for (unsigned int i = 0; i<objects.size(); i++)
    {
        DerivedOne* derived = dynamic_cast<DerivedOne*>(objects[i]);
        if (derived)
            ...
    }

    return 0;
}
You need to use pointers

I think you didn't see my example because we both posted at the same time but there is no need to. It may be faster and more convenient but you can use a ConversionConstructor as well
I'm in a pedantic mood, so I'll point out that it's misleading to call a class "Abstract" if it is, in fact, possible to instantiate an object of that class - as, for example, the OP does in their first snippet :)
That was the first thing I thought :p how the heck did he get a vector with abstract objects?!
Okay so I quickly made the first post, so I'll correct a few things now. First, you guys are right, Abstract is just a class name, really, the class is inherited (sorry, they mean the same to me in English). Anyways, one thing I left out was that my vector of class objects is actually a vector of std::shared_ptr's, so does that work just as well as regular pointers for the purpose of casting?
Also, I want to make sure that this cast is indeed the same instance of the object, not a copy, so is using const in the constructor enough to do that?
Anyways, so I've followed the code samples but I'm having trouble implementing std::shared_ptr's. Here is my code:
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
#include "stdafx.h"
#include <memory>
#include <vector>

class Inherited{

};

class Derived : public Inherited{
public:
	Derived(){}
	~Derived(){}
	Derived(const std::shared_ptr<Inherited> &object) : Inherited(object){} //this throws an error
	void DoSomething(){}
};


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	//I can ensure that the first object is a Derived object
	Derived derived;
	objects.push_back(std::make_shared<Inherited>(derived));

	//I would like to simply call objects[0].DoSomething(), but that won't happen, so I type cast
	Derived(objects[0]).DoSomething();

	return 0;
}

The error that the copy ctor throws is
IntelliSense: no instance of constructor "Inherited::Inherited" matches the argument list
argument types are: (const std::shared_ptr<Inherited>) c:\Users\jordan\Documents\Visual Studio 2012\Projects\Website Script\Website Script\Website Script.cpp


I think this means that I should also give my Inherited class a copy ctor, but what should this look like?
Last edited on
First, you guys are right, Abstract is just a class name, really, the class is inherited (sorry, they mean the same to me in English).

Do you understand what the difference is? Do you understand what an abstract class is?

Anyways, one thing I left out was that my vector of class objects is actually a vector of std::shared_ptr's, so does that work just as well as regular pointers for the purpose of casting?

Yes. Shared pointers have polymorphism, just like C-style plain pointers.

Also, I want to make sure that this cast is indeed the same instance of the object, not a copy, so is using const in the constructor enough to do that?

Using const won't make any difference regarding that at all. Casting an object will, effectively, make a new, temporary instance of that object.

If you want to use the same instance of an object, then cast a reference or a pointer to the object, not the object itself, just as you're doing.

Also, why are you passing a reference to a shared pointer into your constructor? That will completely bypass the reference-counting behaviour of the shared pointer, which is the main point of using one in the first place! What are you trying to achieve by using a reference here?

The error that the copy ctor throws is [...]
I think this means that I should also give my Inherited class a copy ctor

The error message is telling you that you're attempting to invoke a constructor of Inherited that takes a reference to a shared pointer to Inherited. That's not a copy constructor, it's just a constructor that takes an argument. The term "copy constructor" has a very specific meaning.

Any textbook, or tutorial on classes, should show you the syntax for creating a constructor that takes an argument. Since you haven't shown us your definition of Inherited - just an empty code block - we can't possibly know what it might need to do in this specific case.

It seems to me that your design isn't quite right for this. A vector is for holding elements of the same type, that can be treated the same. If you want an entity that contains an item of one type, Derived*, and then several items of another type, Inherited*, wouldn't you be better off having a struct/class that contains a Derived* member, plus a vector of Inherited*?

One of these things is not like the others, so why try and cram them into the same vector? If one of the objects is a special case, and is going to be used differently from the other objects, then treat it clearly and explicitly as a special case. Then you won't have to jump through hoops trying to cast from a base class to a derived one.
Last edited on
So, when using pointers you can use polymorphism, because shared pointers give may give you the raw pointer.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Inherited{

};

class Derived : public Inherited{
public:
	void DoSomething(){}
};


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	//I can ensure that the first object is a Derived object
	Derived derived;
	objects.push_back(std::make_shared<Inherited>(derived));

	//I would like to simply call objects[0].DoSomething(), but that won't happen, so I type cast
	static_cast<Derived*>(objects[0].get())->DoSomething();
// objects[0].get() gives you the raw pointer

	return 0;
}



Do you allways want to invoke the DoSomething method if the class is derived?
make the Method virtual to reach true polymorphism! :D

Note: NOT use make_shared, instead just create a new shared ptr.
If you want even better performance you can use std::move

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <vector>
#include <memory>

class Inherited{
public:
    virtual void DoSomething() { std::cout << "inherited" << std::endl; }
};
class Derived : public Inherited{
public:
    virtual void DoSomething() { std::cout << "derived" << std::endl; }
};

int main(int argc, char* argv[])
{
    std::vector<std::shared_ptr<Inherited>> objects;
    objects.push_back(std::shared_ptr<Inherited>(new Derived()));
    // objects.push_back(std::move(std::shared_ptr<Inherited>(new Derived())));

    // now without casting:
    objects[0].get()->DoSomething(); // derived

    return 0;
}
Last edited on
Hi,

If I could add something to help explain Gamer2015's last post a bit.

A pointer to a Derived class is a valid pointer to a Base class, even though the Base may be abstract. So we can have a container or function that is declared to take a pointer to Base. Then we push a pointer to Derived into our container, or call our function with a pointer to Derived as an argument, or use the pointer to call a class function, or do all 3.

This works in the trivial case where the function being called is in the Derived class, but it also works when it is an implemented virtual function higher up in the inheritance tree.

So Gamer2015's second solution is usually what people need when they ask about casting downwards. It is kind of the reverse of what the OP might have been expecting: Instead of down casting, they send a pointer to Derived and C++ does the right thing.

I would normally expect the base class function to be pure virtual, and then defined as necessary in the Derived classes. Although I understand it was shown like this for demonstration purposes.

Anyway I hope that helped a bit :+)

Regards

On commonly used terms -- these names you will see often in examples:
1
2
3
4
5
6
7
class Base {
  // code
};

class Derived : public Base {
  // code
};
Okay wow this might be a huge learning session for me. So if I'm correct, calling objects[0].get()->DoSomething(); will do the Derived method of DoSomething() as long as DoSomething() is declared as virtual void in the Base class? and let's say I called objects[2].DoSomething(), then nothing would happen because the function is pure virtual? (i.e. it would be safe for me to do this?)
As for MikeyBoy's answer, yeah the design sucks, I'm working on my first full length game for school and I don't have much knowledge in what's a good design.

Edit: No, that doesn't seem to work.
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
#include "stdafx.h"
#include <memory>
#include <vector>
#include <iostream>

class Inherited{
public:
	Inherited(){}
	~Inherited(){}

	virtual void DoSomething(){ std::cout << "Base"; }
};

class Derived : public Inherited{
public:
	Derived(){}
	~Derived(){}
	//Derived(const std::shared_ptr<Inherited> &object) : Inherited(object){}
	virtual void DoSomething(){ std::cout << "Derived"; }
};


int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	//I can ensure that the first object is a Derived object
	Derived derived;
	objects.push_back(std::make_shared<Inherited>(derived));

	//I would like to simply call objects[0].DoSomething(), but that won't happen, so I type cast
	static_cast<Derived*>(objects[0].get())->DoSomething(); //prints "Base"
        objects[0].get()->DoSomething(); // also prints "Base"
	system("pause");

	return 0;
}


What have I done wrong here? How would I get objects[0] to print "Derived"?
Last edited on
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
#include <memory>
#include <vector>
#include <iostream>

class Inherited{
public:
	Inherited(){}
	~Inherited(){}

	virtual void DoSomething() { std::cout << "Base\n"; }
};

class Derived : public Inherited{
public:
	Derived(){}
	~Derived(){}
	virtual void DoSomething() { std::cout << "Derived\n"; }
};


int main()
{
	std::vector<std::shared_ptr<Inherited>> objects;
	objects.push_back( std::shared_ptr<Inherited>( new Derived )   );
	objects.push_back( std::shared_ptr<Inherited>( new Inherited ) );
	objects.push_back( std::shared_ptr<Inherited>( new Derived )   );

	for ( const auto & x : objects )
	{
		x.get()->DoSomething();
	}

	return 0;
}

Derived
Base
Derived

Your line 28 effectively calls new Inherited( derived )

as long as DoSomething() is declared as virtual void in the Base class?

Declared pure virtual:
1
2
3
4
5
6
7
class Inherited{
public:
	Inherited(){}
	~Inherited(){}

	virtual void DoSomething() = 0;  // no implementation
};

A class with at least one pure virtual member is abstract.
Last edited on
let's say I called objects[2].DoSomething(), then nothing would happen because the function is pure virtual?

An attempt to call a pure virtual method will cause a compiler error if you're doing it in such a way that the compiler can tell that's what you're doing. If not, then it will cause your application to crash.

Firstly: It is not even possible to call a pure virtual method.
You would have to make an object of that type but the compiler will prevent that.

Secondly: Be careful what you are doing.
Be very carefully! :o

1
2
3
4
5
6
7
8
9
10
11
int main(int argc, char* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	Derived derived; // Object on stack
	objects.push_back(std::make_shared<Inherited>(derived)); // shared ptr to object on stack

	return 0;
// derived goes out of scope -> destructor
// last pointer to derived goes out of scope -> destructor 
// -> freed the same memory twice -> crash
}


You should work with pointers here... everywhere...
and std::make_shared doesn't work with pointers
So you have to make a new shared ptr (std::shared_ptr<Inherited>(derived)

1
2
3
4
5
6
7
8
9
10
11
12
13
int main(int argc, char* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	Derived* derived = new Derived(); // Object on Heap
	objects.push_back(std::shared_ptr<Inherited>(derived)); // shared ptr to object on Heap

        objects[0].get()->DoSomething(); // prints derived

	return 0;
// pointer to derived goes out of scope but didn't free memory
// last pointer to derived goes out of scope -> destructor 
// -> freed the same memory only once -> no crash
}
Thanks, okay so would using this method require me to declare all the Derived functions that I want to call in the Base class. As in, is there no other option besides this? Here is what I mean in the comments below
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Inherited{
public:
	Inherited(){}
	~Inherited(){}

	virtual void DoSomething(){}
        /*so even though I can gurantee that no other Inherited objects will be
calling DoSomething(), I have to declare it in the Inherited class anyways
so that the Derived pointer can call it?*/
};

class Derived : public Inherited{
public:
	Derived(){}
	~Derived(){}
	//Derived(const std::shared_ptr<Inherited> &object) : Inherited(object){}
	virtual void DoSomething(){ std::cout << "Derived"; }
/*so here I am basically defining DoSomething() a second time, even though it
will never be used in its first definition in Inherited. Is there any way to avoid this?*/
};
Be careful what you are doing.
Be very carefully! :o

Agreed. However,
1
2
Derived foo; // Object on stack
auto pfoo = std::make_shared<Inherited>( foo ); // shared ptr to object on stack 

That has a call to make_shared. The make_shared calls new.
The dynamically allocated Inherited object is constructed by calling an Inherited constructor that accepts object foo as argument. That would be the default copy constructor.

The created shared_ptr does thus point safely to an Inherited object in the heap. No memory management hazard (this time).

The real problem is that the pointer points to genuine Inherited object that is mere copy of the Inherited portion of the foo object.

If Inherited were abstract, the call to make_shared would not compile.


Extra fun: a pure virtual function can have implementation. The class is still abstract and thus cannot be instantiated, but the derived non-abstract classes can call the explicit implementation. Example of use: provide default implementation derived classes while keeping the base abstract.


Casting pointers and calling virtual functions is runtime polymorphism. The polymorphic functionality depends on storing and dereferencing pointers during runtime. Templates offer compile-time polymorphism; no pointers nor dereferencing during runtime, so less memory consumption and instructions. Templates, however, have to be set on stone during compilation.
Scratch my last answer, I think I found a way. Can somebody tell me if this code is bad practice or has any flaws?
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
#include "stdafx.h"
#include <memory>
#include <vector>
#include <iostream>

class Inherited{
public:
	Inherited(){}
	~Inherited(){}
	Inherited(const std::shared_ptr<Inherited> &in){ *this = in; }
};

class Derived : public Inherited{
public:
	Derived(){}
	~Derived(){}
	Derived(const std::shared_ptr<Inherited> &object) : Inherited(*object){}
/*okay so in the above ctor, should I have Inherited(object) or is Inherited(*object) correct?
as in, which ensures that I pass along the same instance of the object and doesn't splice the object?*/
	virtual void DoSomething(){ std::cout << "Derived"; }
};

int _tmain(int argc, _TCHAR* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	objects.push_back(std::shared_ptr<Inherited>(new Derived()));
	static_cast<Derived*>(objects[0].get())->DoSomething();
//now I don't have to define DoSomething() twice, but does this method work correctly or are there flaws?
	system("pause");

	return 0;
}
Last edited on
1
2
Be careful what you are doing.
Be very carefully! :o


Agreed. However,

Derived foo; // Object on stack
auto pfoo = std::make_shared<Inherited>( foo ); // shared ptr to object on stack

That has a call to make_shared. The make_shared calls new.
The dynamically allocated Inherited object is constructed by calling an Inherited constructor that accepts object foo as argument. That would be the default copy constructor.


Thank you for pointing that out.
I have no experience using std::make_shared but that makes sence.
I came across the problem because i wrote std::shared_ptr<Inherited>(&derived); so i wanted to share that knowledge as he may face the same problem anytime soon


Scratch my last answer, I think I found a way. Can somebody tell me if this code is bad practice or has any flaws?

Bad practice and flaws.

flaws:
- you have the virtual method only defined in the Derived class.
- Your constructos that take a shared ptr have flaws.
*this = in; states that the binary representation of *this becomes that of in.
But that wouldn't make sence for 2 different types right?
Also, this will not compile unless you implement a conversion operator.
// Inherited(const std::shared_ptr<Inherited> &in){ *this = in; }

bad practice:
- including header file that is not used ("stdafx.h")
- please change _tmain to main and _TCHAR to char if possible
- implementing not needed or default looking default-constructor and destructor

the rest seems fine :)
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
#include <memory>
#include <vector>
#include <iostream>

class Inherited{
public:
        // both not neccessary at the moment
	// Inherited(){}
	// ~Inherited(){}
        // Inherited(const std::shared_ptr<Inherited> &in){ *this = in; }

        // you do need that if you don't want to cast
	virtual void DoSomething() { std::cout << "Inherited"; }
};
class Derived : public Inherited{
public:
        // both not neccessary at the moment
	// Derived(){}
	// ~Derived(){}
	// Derived(const std::shared_ptr<Inherited> &object) : Inherited(*object){}
	virtual void DoSomething(){ std::cout << "Derived"; }
};

int main(int argc, char* argv[])
{
	std::vector<std::shared_ptr<Inherited>> objects;
	objects.push_back(std::shared_ptr<Inherited>(new Derived()));

        // no static cast needed because of virtual Method
	objects[0].get()->DoSomething();

	system("pause");

	return 0;
}
Last edited on
The code example that you provided is no doubt a great way for me to go, but the thing is that with my vector of all game objects, they'll be inheriting from lots of different classes. So using your design, I'd have to declare all these different classes' functions in my Inherited class (which all game objects inherit from), which basically renders the other classes useless. I'm okay with dynamic_casting until I hit a performance issue but I don't think I will as this game is just a personal one.
tl;dr: Thanks for your code, but if I were to improve upon my own code, what should I change? I.e. what should Inherited(const std::shared_ptr<Inherited> &in){ *this = in; } become? And how would I implement a dynamic_cast, because simply replacing static_cast with that does not work.

- including header file that is not used ("stdafx.h")
- please change _tmain to main and _TCHAR to char if possible

I use visual studio 12, and when I set up a project with a precompiled header, then VS won't even compile unless I include "stdafx.h". VS also writes my main function, and that is just the way that it writes it for me. Should I go ahead and change that or how big of a deal is it?
- you have the virtual method only defined in the Derived class.

Yeah, not sure how that virtual keyword made it into the Derived class, I meant to delete it.
Last edited on
Pages: 12