Creating vectors of objects!

This is a discussion on Creating vectors of objects! within the C++ Programming forums, part of the General Programming Boards category; I have posted earlier today more about my project! I have now sorted out the compile errors with the include ...

  1. #1
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    Creating vectors of objects!

    I have posted earlier today more about my project! I have now sorted out the compile errors with the include files! I worked out that unlike Java or C, for a whole C++ project you only need to write #include "file.cpp" in any one of the files, if you do mulitple include statements for a file (not a library function) it see's it as a redeclaration for some uknown reason!!!

    Anywayz; I have now come up to another problem!!! Basically, here is my design;

    AndGate
    OrGate
    NotGate
    XorGate
    are all classes that inherit common functions from the class LogicGate. My idea was that i could then create a vector to store logic gates of different types in the same place, and therefore have easy tracking of the circuits components! However, When I do this, you can insert instances of the inheritted classes into the vector, but you can't access the added functionality of them!!!

    Does anyone know if this is possible???

    LogicGate:
    int input1
    int input2
    int output
    int id
    int parentID1
    int parentID2

    then functions for gettting and setting pid's, id, inputs, etc. are standard for all logic gates

    AndGate, XorGate, OrGate & NotGate all overide the LogicGate function;
    getOutput - calculates the output depending on the input values supplied to the object.

    So basically, I do the following;
    Code:
    // Create some objects of different gates for testing!
    AndGate myAndGate;
    OrGate myOrGate;
    XorGate myXorGate;
    NotGate myNotGate;
    
    vector <LogicGate> myCircuit(0); // start off circuit empty
    
    // add the objects to the vector
    myCircuit.push_back(myAndGate);
    myCircuit.push_back(myOrGate);
    myCircuit.push_back(myNotGate);
    myCircuit.push_back(myXorGate);
    
    // Set the input values for the gates:
    myCircuit.at(0).setInputs(1,1);
    myCircuit.at(1).setInputs(1,1);
    myCircuit.at(2).setInputs(1,1);
    myCircuit.at(3).setInputs(1); // NOT GATE - Only one input!!! - function over-riding in use.
    
    // Now get the outputs for the gates:
    int a = myCircuit.at(0).getOutput();
    int b = myCircuit.at(0).getOutput();
    int c = myCircuit.at(0).getOutput();
    int d = myCircuit.at(0).getOutput();
    
    // write outputs...
    cout<<"and: "<<a<<endl<<"or: "<<b<<endl<<"xor: "<<c<<endl<<"not: "<<d<<endl;
    This doesn't seem to be working, but I can assure you that the logic gate classes are all working because i have spent all day checking this to get it perfect!!! ...My only problem is finding a way to store the different gates!

    I thought that by doing it this way, it would work because the getOutput function in class LogicGate is over-ridden by the AndGate, OrGate, NotGate and XorGate classes so in effect all objects within the vector would be the same!!! Obviously i am wrong!!! any guidance, much appriciated!!! Thanks!!! Matt

  2. #2
    ZuK
    ZuK is offline
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    >> whole C++ project you only need to write #include "file.cpp"
    you never #include implementation files
    >> When I do this, you can insert instances of the inheritted classes into the vector, but you can't access the added functionality of them!!!
    what you are experiencing here is called slicing. If you declare a vector of LogicGate then the vector will only hold LogicGates. You have to declare the vector as vector<LogicGate *> and dynamically allocate the derived classes.
    Kurt

  3. #3
    Cat without Hat CornedBee's Avatar
    Join Date
    Apr 2003
    Posts
    8,893
    But that is a lot of management overhead. A better idea is to use a vector of smart pointers such as boost::shared_ptr, or Boost's ptr_vector, which was created specifically for this purpose.

    http://www.boost.org/
    All the buzzt!
    CornedBee

    "There is not now, nor has there ever been, nor will there ever be, any programming language in which it is the least bit difficult to write bad code."
    - Flon's Law

  4. #4
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    RE: Zuc

    ou have to declare the vector as vector<LogicGate *> and dynamically allocate the derived classes.
    Does doing this automaticaly dynamically allocate a derrived class? or is there an extra bit to do the dynamic allocation???

    I.E. i just have to do:

    vector <LogicGate *> theCircuit(0);

    and that should work! ...I'll give it a go now and have a look! cheers buddy!!!

  5. #5
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,794
    No, you have to create those objects and then push them onto the vector or you can push the address of existing objects:

    Code:
    vector<LogicGate*> theCircuit;
    AndGate myAndGate;
    OrGate myOrGate;
    XorGate myXorGate;
    NotGate myNotGate;
    
    // Push address of existing objects onto vector.
    theCircuit.push_back(&myAndGate);
    theCircuit.push_back(&myOrGate);
    theCircuit.push_back(&myXorGate);
    theCircuit.push_back(&myNotGate);
    
    // ...Or you can allocate and push on the fly.
    theCircuit.push_back(new AndGate);
    theCircuit.push_back(new OrGate);
    theCircuit.push_back(new XorGate);
    theCircuit.push_back(new NotGate);
    
    // ...Or allocate dynamically first and then push the pointer later.
    AndGate * myAndGatePtr = new AndGate;
    OrGate  * myOrGatePtr  = new OrGate;
    XorGate * myXorGatePtr = new XorGate;
    NotGate * myNotGatePtr = new NotGate;
    theCircuit.push_back(myAndGatePtr);
    theCircuit.push_back(myOrGatePtr);
    theCircuit.push_back(myXorGatePtr);
    theCircuit.push_back(myNotGatePtr);
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  6. #6
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    Merci Beacoup!!!

    Thankyou for a quick reply!!! ...I will go an have a play right now an see what happens!!!!

  7. #7
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,412
    Do follow Cornedbee suggestion if you plan to use dynamically allocated array elements.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  8. #8
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    Some errors occuring!!!

    Regarding the last post! It would be really nice (to fit in with my ideas about how to solve my problem) if i could use the method:

    Code:
    theCircuit.push_back(new AndGate);
    I tried to implement this, but i come up with these errors...

    Code:
    Compiling...
    CIRCUIT.CPP
    D:\WORK\CIRCUIT.CPP(33) : error C2228: left of '.setInput1' must have class/struct/union type
    D:\WORK\CIRCUIT.CPP(34) : error C2228: left of '.setInput2' must have class/struct/union type
    D:\WORK\CIRCUIT.CPP(35) : error C2228: left of '.getOutput' must have class/struct/union type
    Error executing cl.exe.
    
    CIRCUIT.exe - 3 error(s), 0 warning(s)
    Here is how everything is setup...

    LogicGate:
    Code:
    class LogicGate{
    private:
        int type;    // The type of logic gate
        int theID;   // The ID for the logic gate
        int pID1;    // The first parent for the logic gate
        int pID2;    // The second parent for the logic gate
        int input1;  // The first input value for the logic gate
        int input2;  // The second input value for the logic gate
        int output;  // The output value for the logic gate
    public:
        // use default constructor
        // Class Methods:
        int getID();               // returns gates ID
        int getPID1();             // returns gates first parent ID
        int getPID2();             // returns gates second parent ID
        void setPID1(int);         // sets ID of gates first parent
        void setPID2(int);         // sets ID of gates second parent
        void setInput1(int);       // sets gates first input value
        void setInput2(int);       // sets gates second input value
        int getInput1();           // returns value of first input
        int getInput2();           // returns value of second input
        // Virtual Methods:
        //virtual int getOutput();   // returns gates output value
    };
    AndGate:
    Code:
    class AndGate : public LogicGate {
    public:
        // Class methods:
        int getOutput();
    };
    and the file to run a quick test program... [Circuit.cpp]
    Code:
    #include <vector>
    #include <iostream>
    using namespace std;
    
    // Include the different types of logic gate that use this class
    #include "LogicGate.cpp"
    #include "AndGate.cpp"
    //#include "OrGate.cpp"
    //#include "XorGate.cpp"
    //#include "NotGate.cpp"
    
    int main(){
        int x,y,z;
        vector <LogicGate*> theCircuit(0);
        cout<<"enter input 1: ";
        cin>>x;
        cout<<endl<<"enter input 2: ";
        cin>>y;
        theCircuit.push_back(new AndGate);
        theCircuit.at(0).setInput1(x);
        theCircuit.at(0).setInput2(y);
        z = theCircuit.at(0).getOutput();
        cout<<endl<<"output is: "<<z<<endl;
    	return 0;
    }
    I hope that it is just a simple problem!!! ...I am beginning to see light at the end of the tunnel now!!! having not understood a thing about OO Programing (im a low-level C programmer!) Im starting to understand these concepts, and they seem really good!!! ...Just need to learn about how to use them properlly now!!!!! LOL!!!!!

    Again... Thanks to everyone that is helping! couldn't do it without you guys!!! ...I just hope i can do the same in the near future!!!!

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    First, you don't need the 0 when you create the theCircuit vector, it is empty by default. Second, your call to push_back is correct. Third, the errors are because you are storing pointers inside your vector, so you must use '->' to access the member functions, not '.'.

    Fourth, you aren't deleting the memory you created with new. You should give LogicGate a virtual destructor, and then go through every pointer in your vector and call delete on it before your program ends. Or you could also follow CornedBee's suggestion and use shared_ptr or ptr_vector.

  10. #10
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121
    Sweet! ...Got rid of those errors! but now the error is:

    Code:
    --------------------Configuration: CIRCUIT - Win32 Debug--------------------
    Compiling...
    CIRCUIT.CPP
    D:\WORK\CIRCUIT.CPP(35) : error C2039: 'getOutput' : is not a member of 'LogicGate'
            d:\work\logicgate.cpp(7) : see declaration of 'LogicGate'
    Error executing cl.exe.
    
    CIRCUIT.OBJ - 1 error(s), 0 warning(s)

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    That should be pretty self-explanatory.

  12. #12
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121
    Quote Originally Posted by Daved
    That should be pretty self-explanatory.
    I understand what the error is!!! ...However, This is my problem... I thought that by putting the AndGate object inside the vector would allow me to access the extra function given by the logic gate AndGate, if you see above in the source code, you will notice in class AndGate, there is just one function; getOutput(), so why can i not access this function???

  13. #13
    Registered User
    Join Date
    Jan 2005
    Posts
    7,317
    I see. The problem seems to be with your understanding of polymorphism. By holding LogicGate pointers in your vector, you are able to access any of the functions that are available in LogicGate. This is powerful because you can override the functions in the derived classes to do different things. For example, if you create a virtual getOutput function in LogicGate, then you can implement this function in AndGate to do AndGate specific things, and override it in OrGate and do OrGate specific things.

    You cannot call functions that are only defined in AndGate from a LogicGate pointer, and you don't want to anyway because that makes the code less generic and is bad design.

    The solution is to make a virtual getOutput function inside LogicGate and the AndGate version will be called automatically.

  14. #14
    (?<!re)tired Mario F.'s Avatar
    Join Date
    May 2006
    Location
    Portugal
    Posts
    7,412
    Hold on on the exclamation marks. It looks like you are angry.... Are you angry?

    Your vector has been defined as vector<base_class*>. Think about it. What does it really mean?

    It means that the vector "accepts" objects of base_class type. So far so good. The rules for Dynamic Binding allow you to define derived objects from a base class. But ths is where it gets tricky, you must not forget that when you are accessing the vector elements, you are effectively accessing elements of base_class* type. And your base class doesn't have that member function defined.

    You have 3 options:

    . You define that function for your base class too and have it do nothing. This is the ugly option.
    . You define your base class as an abstract class by defining the function inside it as
    return_type function_name(arg_list) = 0. This is a good option.
    . You define another class from which your current base class derives and make that new class
    abstract. Your vector will also be changed to hold new_base_class*. You do this if you need to
    create objects of your curren base_class.

    EDIT: I'm assuming your function makes no sense within the context of your current base_class. If however, it makes sense to have also a GetOutput() function for LogicGate, then you should define it normally inside your current base_class.
    Last edited by Mario F.; 08-08-2006 at 03:52 PM.
    The programmer’s wife tells him: “Run to the store and pick up a loaf of bread. If they have eggs, get a dozen.”
    The programmer comes home with 12 loaves of bread.


    Originally Posted by brewbuck:
    Reimplementing a large system in another language to get a 25% performance boost is nonsense. It would be cheaper to just get a computer which is 25% faster.

  15. #15
    Matt Conway bobthebullet990's Avatar
    Join Date
    Nov 2005
    Location
    Cambridge
    Posts
    121

    I'm getting angry now!!!

    RIGHT! Now im fed up! ...it worked!!!! ...then i was excited cause i could get on with writing code that actually does something interesting... like add logic gates to circuits!!!

    HOWEVER!!! I want my C functions back because they actually work!!! these C++ variations or whatever you want to call them are not working!!!

    Code:
    int main(){
        int x,y,z;
        vector <LogicGate*> theCircuit;
        cout<<"enter input 1: ";
        cin>>x;
        cout<<endl<<"enter input 2: ";
        cin>>y;
    	cout<<endl;
        theCircuit.push_back(new AndGate);
        theCircuit.at(0)->setInput1(x);
        theCircuit.at(0)->setInput2(y);
        z = theCircuit.at(0)->getOutput();
        cout<<"output is: "<<z<<endl;
    	return 0;
    }
    So i did a quick test and it appears that it is reading the first input correctly and if i enter 1, it stores 1, however, for y, it reads something stupid like -8455748485758, so what the hell!!! why can't it just do what it says on the tin!!!! anyone know some stupid bit of code you have to add???? This is just ........ing me off now; what happend to printf and scanf, they are tried and tested and work! cin is crap. FACT.

Page 1 of 2 12 LastLast
Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Profiler Valgrind
    By afflictedd2 in forum C++ Programming
    Replies: 4
    Last Post: 07-18-2008, 09:38 AM
  2. A question about dynamically creating an array of objects
    By edd1986 in forum C++ Programming
    Replies: 3
    Last Post: 03-19-2006, 11:30 AM
  3. vectors and objects
    By barneygumble742 in forum C++ Programming
    Replies: 3
    Last Post: 07-04-2005, 08:53 AM
  4. creating objects in c++
    By sachitha in forum C++ Programming
    Replies: 2
    Last Post: 09-19-2004, 12:19 PM
  5. Vectors of pointers to objects
    By Myownworstenemy in forum C++ Programming
    Replies: 3
    Last Post: 09-01-2003, 11:23 PM

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