why dynamic_cast failed?



 DEVELOP > c-Plus-Plus > why dynamic_cast failed?

LINK TO THIS PAGE  


rating :  0   |  0


  Page 1 of 1

1

 
Topic: DEVELOP > c-Plus-Plus
User: ""
Date: 02 Sep 2006 03:48:26 PM
Object: 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;
}
.

User: "Thomas J. Gritzan"

Title: Re: why dynamic_cast failed? 02 Sep 2006 04:40:40 PM
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
.
User: ""

Title: Re: why dynamic_cast failed? 02 Sep 2006 05:42:39 PM
Thank you Thomas. I have to have at least one virtual function to make
dynamic_cast work.
.
User: "Bo Persson"

Title: Re: why dynamic_cast failed? 03 Sep 2006 02:16:45 AM
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
.

User: "Earl Purple"

Title: Re: why dynamic_cast failed? 03 Sep 2006 07:13:57 AM
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.
.



User: ""

Title: Re: why dynamic_cast failed? 02 Sep 2006 04:16:25 PM
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;
}

.
User: "Thomas J. Gritzan"

Title: Re: why dynamic_cast failed? 02 Sep 2006 04:27:58 PM
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
.



  Page 1 of 1

1

 


Related Articles
 

NEWER

pg.1232     pg.940     pg.716     pg.544     pg.412     pg.311     pg.234     pg.175     pg.130     pg.96     pg.70     pg.50     pg.35     pg.24     pg.16     pg.10     pg.6     pg.3     pg.1

OLDER