473,405 Members | 2,415 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

why dynamic_cast failed?

Here I have four classes: RefBook and TextBook, which are inheritated
from base class Book; and a class Database, which has an array to store
the pointers to those two kinds of books. Now I am writing a member
function of Database, print(), which prints the information of all the
RefBooks in the array by using dynamic_cast. Below is my code(some
implemetations omitted). I don't know why the compiler complains that
"cannot dynamic_cast type Book* to type RefBook* (source type is not
polymophic)".

class Book
public:
Book(const string& = "");
const string& getName() const;
private:
string name_;
};

class RefBook : public Book {
public:
RefBook(const string&, char);
char getSubject() const;
void print() const;
private:
char subject_;
};

class TextBook : public Book {
public:
TextBook(const string&, int);
private:
int course_;
};

class Database {
public:
Database();
enum {SIZE = 100};
void addBook(Book*);
void printRef() const;
private:
Book* book_[SIZE];
int number_;
};

void Database::printRef() const {
for(int i = 0; i < number_; i++)
// compiler complains "source type is not polymophic", what's
wrong?
if(RefBook* rb = dynamic_cast<RefBook*(book_[i]))
cout << rb->print() << endl;
}
int main() {
Book* a = new RefBook("Relativity Theory", 'p');
Book* b = new TextBook("Database Management", 113);
Database db;
db.addBook(a);
db.addBook(b);
db.printRef();
delete a;
delete b;
return 0;
}

Sep 2 '06 #1
6 5145
I suspect there is another problem here. The addBook function takes the
type Book* as a parameter.
class Database {
public:
Database();
enum {SIZE = 100};
void addBook(Book*);
void printRef() const;
private:
Book* book_[SIZE];
int number_;
};
but when I use it in "db.addBook(a)", a type conversion from RefBook*
to Book* occured. Is this a "slicing problem"? If so, do I have to
define two addBook funtions(one for RefBook and one for TextBook) to
add books in the database?
int main() {
Book* a = new RefBook("Relativity Theory", 'p');
Book* b = new TextBook("Database Management", 113);
Database db;
db.addBook(a);
db.addBook(b);
db.printRef();
delete a;
delete b;
return 0;
}
Sep 2 '06 #2
xg****@gmail.com schrieb:
I suspect there is another problem here. The addBook function takes the
type Book* as a parameter.
yes.
>class Database {
public:
Database();
enum {SIZE = 100};
void addBook(Book*);
void printRef() const;
private:
Book* book_[SIZE];
int number_;
};

but when I use it in "db.addBook(a)", a type conversion from RefBook*
to Book* occured.
No, "a" already is a Book*. But it points to a RefBook object.
Is this a "slicing problem"?
No. Slicing occurs with values, not with pointers.
>int main() {
Book* a = new RefBook("Relativity Theory", 'p');
Book* b = new TextBook("Database Management", 113);
Database db;
db.addBook(a);
db.addBook(b);
db.printRef();
delete a;
delete b;
return 0;
}

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Sep 2 '06 #3
xg****@gmail.com schrieb:
Here I have four classes: RefBook and TextBook, which are inheritated
from base class Book; and a class Database, which has an array to store
the pointers to those two kinds of books. Now I am writing a member
function of Database, print(), which prints the information of all the
RefBooks in the array by using dynamic_cast. Below is my code(some
implemetations omitted). I don't know why the compiler complains that
"cannot dynamic_cast type Book* to type RefBook* (source type is not
polymophic)".
The problem is: dynamic_cast works only with polymorphic types. That means,
the classes have to have virtual functions.
class Database {
public:
Database();
enum {SIZE = 100};
void addBook(Book*);
void printRef() const;
private:
Book* book_[SIZE];
Is there a reason for a fixed array size here? What if you have more than
100 books?

Make that a std::vector<Book*>.
Think about the ownership of the books. Should the database call "delete"
on the pointers in its destructor?
void Database::printRef() const {
for(int i = 0; i < number_; i++)
// compiler complains "source type is not polymophic", what's
wrong?
if(RefBook* rb = dynamic_cast<RefBook*(book_[i]))
cout << rb->print() << endl;
}
Bad idea. Maintainance hell.

In general, the base class (Book) should have a virtual function "print()"
which is overwritten in the subclasses. Then the database could simply call
print() on all books stored.
But it seems that you want to print out only the RefBook subclasses. Since
I don't know your design here, I can't suggest better alternatives.

Another thing:
cout << rb->print() << endl;
Since RefBook::print() has return type void, this won't compile.

--
Thomas
http://www.netmeister.org/news/learn2quote.html
Sep 2 '06 #4
Thank you Thomas. I have to have at least one virtual function to make
dynamic_cast work.

Sep 2 '06 #5
xg****@gmail.com wrote:
Thank you Thomas. I have to have at least one virtual function to
make
dynamic_cast work.
As you are deleting through a pointer to base class, you must have a
virtual destructor in the base class. That would satisfy the
requirement for dynamic_cast as well.
Bo Persson
Sep 3 '06 #6

xg****@gmail.com wrote:
Thank you Thomas. I have to have at least one virtual function to make
dynamic_cast work.
You'll want a virtual destructor in Book and a virtual method that
Database calls. Then get rid of the dynamic_cast. dynamic_cast is
generally evil. That doesn't mean you'll never do it but you won't do
it most of the time. There are some exceptions but this isn't one of
them.

To handle the memory management, you'll probably either want to use
shared_ptr (probably simplest) or a type of collection like ptr_vector,
either of which can be found in boost. shared_ptr is going to be part
of the new standard and is already in tr1.

Sep 3 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: KeithO | last post by:
I am having problems calling dynamic_cast<> on a pointer returned by a dynamically loaded library. The problem seems to be related to the fact that I dynamically load the library because if I link...
13
by: GianGuz | last post by:
Everyone knows about the complex and cpu-expensive procedures taken by dynamic_cast to find the right function call in a virtual classes hierarchy. The question I would to rise is when...
3
by: Axter | last post by:
I'm wondering about the practical use of dynamic_cast in reusable or generic code. I'm currently working on a smart pointer that can be used on vector and other STL containers. See following...
1
by: Steven T. Hatton | last post by:
The result shown below doesn't surprise me now. But it did several months ago when I followed some bad advice and tried to check if I had a live object at the address referenced by a pointer. Can...
3
by: Ganesh | last post by:
On devx site, I saw following code. It says when a derived class is tried to cast to base type, it looks at the missing vtable and complains if the object is already deleted. I am of the opinion...
22
by: Boris | last post by:
I'm porting code from Windows to UNIX and ran into a problem with dynamic_cast. Imagine a class hierarchy with three levels: class Level2 derives from Level1 which derives from Base. If you look...
15
by: Grizlyk | last post by:
Hello. Returning to question of manual class type identification, tell me, for ordinary inheritance is C++ garantee that dynamic_cast<Derived*>(Base*) can be implemented similarly to ...
25
by: lovecreatesbea... | last post by:
Suppose I have the following three classes, GrandBase <-- Base <-- Child <-- GrandChild The following cast expression holds true only if pBase points object of type of ``Child'' or...
18
by: Eric | last post by:
Ok...this seems to be treading into some really esoteric areas of c++. I will do my best to explain this issue, but I don't fully understand what is happening myself. I am hoping that the problem...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.