You are not logged in.

#1 2007-12-03 19:12:48

creatorx
Member
Registered: 2005-09-14
Posts: 26

Help with C++ polymorphism

I'm new to C++, I usually use Java. So my question is: I have a pure virtual class that I want to use as an interface, the class is

class DatabaseRecord {
public:
virtual std::string getInsert() = 0;
virtual std::string getTable() = 0;
};

this is only declared in a header file I have no cpp file for this class. I then have a sub class such as

class State : public DatabaseRecord {
private:
std::string name;
public:
State();
virtual ~State();
std::string getInsert();
std::string getTable();
};

this again is a header file. My cpp file for this header looks like,

State::State(){ name = "Test"; }
State::~State(){}

std::string State::getInsert() {
std::stringstream ss;
ss << "Test " << name << "T";
return ss.str();
}

std::string State::getTable() {
std::stringstream ss;
ss << "CREATE " << name;
return ss.str();
}

The problem is that when I call either method getInset or getTable the variable "name" is empty.
I mean when I print out the return string it dosent print the contents of name "Test".

Any Help will be greatly appreciated.

Offline

#2 2007-12-03 19:29:28

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: Help with C++ polymorphism

So what you're saying is that you see, for example,

Test T

when you print out the return value of getInsert(), instead of the expected

Test TestT

correct?

Using the code you're provided here works as expected for me, with this main:

#include "State.h"
#include <iostream>

int main()
{
    State s; 
    std::cout << s.getInsert() << std::endl;

    DatabaseRecord* db = new State();
    std::cout << db->getInsert() << std::endl;

    delete db;
}

Last edited by Cerebral (2007-12-03 19:29:47)

Offline

#3 2007-12-03 19:48:00

creatorx
Member
Registered: 2005-09-14
Posts: 26

Re: Help with C++ polymorphism

Well here is what am doing I first create an object of type DatabaseRecord such as, and then push it into a List which is declared as std::list<DatabaseRecord *>  records;

State s;
records.push_back(&s);

The in another segment of code I do this;

if(!records.empty()) {
    std::list<DatabaseRecord *>::const_iterator it;
    for(it = records.begin(); it != records.end(); ++it) {
        std::cout << (*it)->getInsert() << std::endl;
    }
    records.clear();
}

but it doesn't work. sad

The implementation is a DLL file for Windows and it have export declarations for methods such as;
AREXPORT std::string getInsert();

I left them out for the sake of simplicity, do you think this has something to do with this?

I really appreciate your help.  Thank you

Offline

#4 2007-12-03 20:06:22

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: Help with C++ polymorphism

creatorx wrote:

Well here is what am doing I first create an object of type DatabaseRecord such as, and then push it into a List which is declared as std::list<DatabaseRecord *>  records;

State s;
records.push_back(&s);

The in another segment of code I do this;

if(!records.empty()) {
    std::list<DatabaseRecord *>::const_iterator it;
    for(it = records.begin(); it != records.end(); ++it) {
        std::cout << (*it)->getInsert() << std::endl;
    }
    records.clear();
}

but it doesn't work. sad

I think this may be the source of your problem - especially if you do it exactly the way you describe.

For example, this will NOT work (for the reasons indicated in the comments):

void push_back_new_state() {
  State s;  // allocate a new State object, local to this block
  records.push_back(&s);
} // ONOZ!  The block ends, State s is destroyed and &s is no longer valid!

void read_states() {
  if(!records.empty()) {
    std::list<DatabaseRecord *>::const_iterator it;
    for(it = records.begin(); it != records.end(); ++it) {
      std::cout << (*it)->getInsert() << std::endl;
    }
    records.clear();
  }
}

int main() {
  push_back_new_state(); // State s is destroyed when this call ends
  read_states(); // This call will try to read from the destroyed State s. BAD!
}

What you need to do is allocate on the heap, not the stack:

void push_back_new_state() {
  // allocate a new State object on the heap - object is not destroyed at the end of this block
  State * s = new State();  
  records.push_back(s);
} // Woot!  the new state object isn't destroyed!

void read_states() {
  if(!records.empty()) {
    std::list<DatabaseRecord *>::const_iterator it;
    for(it = records.begin(); it != records.end(); ++it) {
      std::cout << (*it)->getInsert() << std::endl;
      delete (*it); // make sure we free the memory!  Don't want a leak!
    }
    records.clear();
  }
}

int main() {
  push_back_new_state(); // State s is not destroyed when this call ends
  read_states(); // This call will read from the State s allocated on the heap.  Fine and dandy!
}

Offline

#5 2007-12-03 20:20:18

creatorx
Member
Registered: 2005-09-14
Posts: 26

Re: Help with C++ polymorphism

I could kiss you right now. big_smile:D:D:D
You just solve my problem, i waisted around 12 hours in total searching around in google.
I will just blame my ignorance  on Java.  cool

But, seriously thanks a million.

Offline

#6 2007-12-03 20:34:41

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: Help with C++ polymorphism

No prob - memory management is one of the tricky aspects you've gotta get used to when moving to C++ from Java, where you don't have to manage anything.  Good luck with your app.

Offline

#7 2007-12-03 20:44:10

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Help with C++ polymorphism

For the record, it's probably much simpler for you to use boost::ptr_list<DatabaseRecord> instead of std::list<DatabaseRecord*> as it will manage memory management for you (yay!).

And another thing... list is an expensive container for what you're doing. Try a vector or deque (yay deque!). Those two should actually be more of a default choice than using std::list.

Offline

#8 2007-12-03 20:52:53

Cerebral
Forum Fellow
From: Waterloo, ON, CA
Registered: 2005-04-08
Posts: 3,108
Website

Re: Help with C++ polymorphism

phrakture wrote:

For the record, it's probably much simpler for you to use boost::ptr_list<DatabaseRecord> instead of std::list<DatabaseRecord*> as it will manage memory management for you (yay!).

I guess I really need to learn boost, don't I?  It seems to have many things that are made of win.

Offline

#9 2007-12-03 21:18:01

PJ
Member
From: Sweden
Registered: 2005-10-11
Posts: 602

Re: Help with C++ polymorphism

Not sure if you are thinking of mixing different C++ compilers (one compiling the DLL and another compiling the program which then will load the DLL). If you are going to do that, then it might be a good idea to read more about name mangling.

Last edited by PJ (2007-12-03 21:19:16)

Offline

#10 2007-12-03 23:09:43

phrakture
Arch Overlord
From: behind you
Registered: 2003-10-29
Posts: 7,879
Website

Re: Help with C++ polymorphism

Cerebral wrote:
phrakture wrote:

For the record, it's probably much simpler for you to use boost::ptr_list<DatabaseRecord> instead of std::list<DatabaseRecord*> as it will manage memory management for you (yay!).

I guess I really need to learn boost, don't I?  It seems to have many things that are made of win.

Yeah. boost::ptr_vector<T> is really just a std::vector<boost::shared_ptr<T>> (not exactly, though), and boost::shared_ptr is just a simple reference counted pointer container that deletes when the ref count hits 0. You can also provide custom deleters, which makes it work great with C functions. For instance...

boost::shared_ptr<Display> dpy(XOpenDisplay(), XCloseDisplay);

Yay!

Offline

#11 2007-12-10 18:49:49

creatorx
Member
Registered: 2005-09-14
Posts: 26

Re: Help with C++ polymorphism

Thanks for your replies.  Its working wonderful now.  I also dint know about boost sounds cool.  I will consider next time I work with C++.

Offline

#12 2008-02-06 02:43:06

arew264
Member
From: Friendswood, Texas, US
Registered: 2006-07-01
Posts: 394
Website

Re: Help with C++ polymorphism

Another thing you should be aware of - google "virtual destructor"
I don't know if you have learned about destructors, they are new in C++ from Java, but they are simply functions that are called when an object is deleted. As it is, you are calling the "default destructor", the destructor the compiler writes for you since you don't have one. The problem is that since you are storing pointers to DatabaseRecord objects, the DatabaseRecord destructor will be called instead of the State destructor.
To fix that, you simply create

virtual DatabaseRecord::~DatabaseRecord() { }

and override it wherever needed.

Offline

Board footer

Powered by FluxBB