Classes and structures

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ConfusedAlot
    New Member
    • Mar 2007
    • 17

    Classes and structures

    I have a structured piece of code that i am converting into object orientated, the structured code contains a stuct;


    Code:
    struct OpAmps {
      char Name[20];  // the name of the op-amp (e.g. "741")
      unsigned int PinCount;  // the number of pins in the package
      double SlewRate;  // the slew rate in volts per microsecond
    };

    This struct needs to be included in the OO code as it is a part of the functions - now member functions.

    So far the class i have defined for the OO code is;

    Code:
    class OpAmpDb
    {
    public:
    	OpAmpDb();
    	void Enter(OpAmps&, unsigned long&);
    	void Save(const OpAmps*, unsigned long);
    	void Load(OpAmps*, unsigned long&);
    	void Sort(OpAmps*, unsigned long);
    	int SortName(const void*, const void*);
    	int SortSlewRate(const void*, const void*);
    	void Display(const OpAmps*, unsigned long);
    private:
    	int Num;
    };
    Problem - the constructor is not working properly, i define the member function;

    OpAmpDb::OpAmpD b()


    and get an error that i cannot redeclare it! I am very confused about this, not quite sure where to put my struct definition in the new OO code or why my constructor will not work!!

    Please help!!
    Last edited by AdrianH; May 5 '07, 03:52 PM. Reason: Please use [code][/code] tags for readibility
  • AdrianH
    Recognized Expert Top Contributor
    • Feb 2007
    • 1251

    #2
    Given the limited amount of information you have posted, I would say that you are defining the body of OpAmpDb::OpAmpD b() in the header file. I could be wrong though. But in the off chance I am correct, but the function definition in a source file.

    If I am wrong, it may help if you post the error messages being emitted from the comipler.


    Adrian

    Comment

    • ConfusedAlot
      New Member
      • Mar 2007
      • 17

      #3
      I have 2 header files and one cpp file.

      object.h contains;

      Code:
      struct OpAmps {
        char Name[20];  // the name of the op-amp (e.g. "741")
        unsigned int PinCount;  // the number of pins in the package
        double SlewRate;
      };
        
      class OpAmpDb
      {
      public:
      	OpAmpDb();
      	void Enter(OpAmps&, unsigned long&);
      	void Save(const OpAmps*, unsigned long);
      	void Load(OpAmps*, unsigned long&);
      	void Sort(OpAmps*, unsigned long);
      	int SortName(const void*, const void*);
      	int SortSlewRate(const void*, const void*);
      	void Display(const OpAmps*, unsigned long);
      private:
      	int Num;
      };


      memfun contains;


      Code:
      OpAmpDb::OpAmpDb();
      {
      	OpAmpObject OpAmp[DATABASE_MAX];
      	unsigned long database_length = 0;  // the number of elements in the database
      	char UserInput;
                            
        // loop until the user wishes to exit
        while (1) {
          
          // show the menu of options
          cout << endl;
          cout << "Op-amp database menu" << endl;
          cout << "--------------------" << endl;
          cout << "1. Enter a new op-amp into the database" << endl;
          cout << "2. Save the database to disk" << endl;
          cout << "3. Load the database from disk" << endl;
          cout << "4. Sort the database" << endl;
          cout << "5. Display the database" << endl;
          cout << "6. Exit from the program" << endl << endl;
          
          // get the user's choice
          cout << "Enter your option: ";
          cin >> UserInput;
          cout << endl;
          
          // act on the user's input
          switch(UserInput) {
            case '1':
      		  OpAmpObject.Enter(OpAmp[database_length], database_length);
              break;
            
            case '2':
      		  OpAmpObject.Save(OpAmp, database_length);
              break;
            
            case '3':
      		  OpAmpObject.Load(OpAmp, database_length);
              break;
            
            case '4':
      		  OpAmpObject.Sort(OpAmp, database_length);
              break;
            
            case '5':
      		  OpAmpObject.Display(OpAmp, database_length);
              break;
      
            case '6':
              return 0;
      
            default:
              cout << "Invalid entry" << endl << endl;
              break;
          }
        }
      }
      including other member function definitions. the cpp file contains;


      Code:
      #include <stdafx.h>
      #include <iostream>
      #include <fstream>
      #include <string.h>
      #include "object.h"
      #include "MemFun.h"
      
      
      int main()
      {
      	OpAmpDb OpAmpObject;
      
      	return 0;
      }

      It does not like that ive put all the member functions into another file, and it still says that i cannot redefine the member function

      error C2761 '{ctor}' : member function redelaration not allowed

      Comment

      • AdrianH
        Recognized Expert Top Contributor
        • Feb 2007
        • 1251

        #4
        Originally posted by ConfusedAlot
        Code:
        OpAmpDb::OpAmpDb();
        {
        	OpAmpObject OpAmp[DATABASE_MAX];
        	unsigned long database_length = 0;  // the number of elements in the database
        //...
        }
        including other member function definitions. the cpp file contains;

        (snip)

        It does not like that ive put all the member functions into another file, and it still says that i cannot redefine the member function

        error C2761 '{ctor}' : member function redelaration not allowed
        Ahh, I see the problem. It is a redelaration error, not a redefinition error. You have a semicolon after OpAmpDb::OpAmpD b() so the compiler thinks you are trying to redeclare it. That is not allowed. Get rid of the semicolon and it should work.


        Adrian

        P.S. When stating an error, you may wish to post all of the error/warning messages (or at least the first 2-5). It may help in debugging the problem.

        Comment

        • ConfusedAlot
          New Member
          • Mar 2007
          • 17

          #5
          Thank you! so i changed that, and now im having problems with the fact that the object im creating is being converted from a struct to object oriented, except, im not sure how to do this and all the errors are related to the fact that in the menu code the left of .Enter, .Save etc are not class/struct/union! also i have an error that says that OpAmpObject is undeclared, except ive created it in main from the OpAmpDb class;

          Code:
          int main()
          {
          	OpAmpDb OpAmpObject;
          
          	return 0;
          }
          
          
          
          
          
          
          
          #define DATABASE_FILENAME "database.txt"
          
          #define DATABASE_MAX 10
          
          OpAmpDb::OpAmpDb()
          {
          	unsigned long database_length = 0;  // the number of elements in the database
          	char UserInput;
                                
            // loop until the user wishes to exit
            while (1) {
              
              // show the menu of options
              cout << endl;
              cout << "Op-amp database menu" << endl;
              cout << "--------------------" << endl;
              cout << "1. Enter a new op-amp into the database" << endl;
              cout << "2. Save the database to disk" << endl;
              cout << "3. Load the database from disk" << endl;
              cout << "4. Sort the database" << endl;
              cout << "5. Display the database" << endl;
              cout << "6. Exit from the program" << endl << endl;
              
              // get the user's choice
              cout << "Enter your option: ";
              cin >> UserInput;
              cout << endl;
              
              // act on the user's input
              switch(UserInput) {
                case '1':
          		  OpAmpObject.Enter(OpAmp[database_length], database_length);
                  break;
                
                case '2':
          		  OpAmpObject.Save(OpAmp, database_length);
                  break;
                
                case '3':
          		  OpAmpObject.Load(OpAmp, database_length);
                  break;
                
                case '4':
          		  OpAmpObject.Sort(OpAmp, database_length);
                  break;
                
                case '5':
          		  OpAmpObject.Display(OpAmp, database_length);
                  break;
          
                case '6':
                  return 0;
          
                default:
                  cout << "Invalid entry" << endl << endl;
                  break;
              }
            }
          }

          Comment

          • ilikepython
            Recognized Expert Contributor
            • Feb 2007
            • 844

            #6
            Originally posted by ConfusedAlot
            Thank you! so i changed that, and now im having problems with the fact that the object im creating is being converted from a struct to object oriented, except, im not sure how to do this and all the errors are related to the fact that in the menu code the left of .Enter, .Save etc are not class/struct/union! also i have an error that says that OpAmpObject is undeclared, except ive created it in main from the OpAmpDb class;

            Code:
            int main()
            {
            	OpAmpDb OpAmpObject;
            
            	return 0;
            }
            
            
            
            
            
            
            
            #define DATABASE_FILENAME "database.txt"
            
            #define DATABASE_MAX 10
            
            OpAmpDb::OpAmpDb()
            {
            	unsigned long database_length = 0;  // the number of elements in the database
            	char UserInput;
                                  
              // loop until the user wishes to exit
              while (1) {
                
                // show the menu of options
                cout << endl;
                cout << "Op-amp database menu" << endl;
                cout << "--------------------" << endl;
                cout << "1. Enter a new op-amp into the database" << endl;
                cout << "2. Save the database to disk" << endl;
                cout << "3. Load the database from disk" << endl;
                cout << "4. Sort the database" << endl;
                cout << "5. Display the database" << endl;
                cout << "6. Exit from the program" << endl << endl;
                
                // get the user's choice
                cout << "Enter your option: ";
                cin >> UserInput;
                cout << endl;
                
                // act on the user's input
                switch(UserInput) {
                  case '1':
            		  OpAmpObject.Enter(OpAmp[database_length], database_length);
                    break;
                  
                  case '2':
            		  OpAmpObject.Save(OpAmp, database_length);
                    break;
                  
                  case '3':
            		  OpAmpObject.Load(OpAmp, database_length);
                    break;
                  
                  case '4':
            		  OpAmpObject.Sort(OpAmp, database_length);
                    break;
                  
                  case '5':
            		  OpAmpObject.Display(OpAmp, database_length);
                    break;
            
                  case '6':
                    return 0;
            
                  default:
                    cout << "Invalid entry" << endl << endl;
                    break;
                }
              }
            }
            You can't use an instance of a class in the class itself by the name of the instance. You just call the function without adding the "OpAmpObjec t.":
            Code:
            Enter(arguements);
            Save(arguements);
            Also, the "this" keyword refers to the instance the class is called with.

            Comment

            • AdrianH
              Recognized Expert Top Contributor
              • Feb 2007
              • 1251

              #7
              Originally posted by ConfusedAlot
              Thank you! so i changed that, and now im having problems with the fact that the object im creating is being converted from a struct to object oriented, except, im not sure how to do this and all the errors are related to the fact that in the menu code the left of .Enter, .Save etc are not class/struct/union! also i have an error that says that OpAmpObject is undeclared, except ive created it in main from the OpAmpDb class;

              Code:
              int main()
              {
              	OpAmpDb OpAmpObject;
              
              	return 0;
              }
              
              
              
              
              
              
              
              #define DATABASE_FILENAME "database.txt"
              
              #define DATABASE_MAX 10
              
              OpAmpDb::OpAmpDb()
              {
              	unsigned long database_length = 0;  // the number of elements in the database
              	char UserInput;
                                    
                // loop until the user wishes to exit
                while (1) {
                  
                  // show the menu of options
                  cout << endl;
                  cout << "Op-amp database menu" << endl;
                  cout << "--------------------" << endl;
                  cout << "1. Enter a new op-amp into the database" << endl;
                  cout << "2. Save the database to disk" << endl;
                  cout << "3. Load the database from disk" << endl;
                  cout << "4. Sort the database" << endl;
                  cout << "5. Display the database" << endl;
                  cout << "6. Exit from the program" << endl << endl;
                  
                  // get the user's choice
                  cout << "Enter your option: ";
                  cin >> UserInput;
                  cout << endl;
                  
                  // act on the user's input
                  switch(UserInput) {
                    case '1':
              		  OpAmpObject.Enter(OpAmp[database_length], database_length);
                      break;
              //...
                  }
                }
              }
              You havn't programmed in C++ before, have you.

              Scoping rules state that a variable/object declared in another scope is not accessable unless that scope you are accessing from is contained within the scope you are accessing. So:
              Code:
              void fn2()
              {
                bar = 3;
              }
              
              void fn1()
              {
                int bar = 4;
                fn2();
              }
              will not work for the same reason that your code will not work. They are in seperate scopes. (a scope is roughly defined as being encompassed by braces, but need not be in the case of the body of a for/if/while/do. In those cases, the new scope is implicit).

              In your case, you just want to access the 'this' object. The object that the member function belongs to.

              A class has a special type of scope. If you are within a member function of the class, all members are accessable as if they were defined in the global scope (roughly anyway). So:
              Code:
              class A
              {
                int variable;
                A();
                void memberFn();
              };
              
              A:A()
              {
                variable = 3;
                memberFn();
              }
              is valid. Note if you declare something with the same name inside of the member function, this member becomes 'shadowed' and you cannot access it directly. To access it indirectly you would do this:
              Code:
              void A::memberFn()
              {
                int variable = 6;
                printf("member 'variable' = %d\n", this->variable); // displays 3
                printf("auto 'variable' = %d\n", variable); // displays 6
              
              }
              Given what I just stated, can you now figure out what you have done wrong?


              Adrian

              Comment

              • ConfusedAlot
                New Member
                • Mar 2007
                • 17

                #8
                Im not sure...

                I have declared all the functions within the class now, so they are all accessible to one another, in the menu system i have for example;

                Code:
                      case '1':
                		  Enter(OpAmpObject[database_length], database_length);
                        break;
                I know that OpAmpObject is not defined in the class, and therefore cannot be accessed even though it is declared in main as type OpAmps, the point that is causing my main problem is what to put as the first name in the brackets above, anything i put in it does not like....

                your right, i havent done much c++, and i get thoroughly confused as im also learning vb.net at the same time!!!

                Thank you again for your help!

                Comment

                • ConfusedAlot
                  New Member
                  • Mar 2007
                  • 17

                  #9
                  One last thing,

                  I have a sort member function that passes data to other functions;

                  Code:
                  void OpAmps::Sort(OpAmps* Op, unsigned long length)
                  
                    switch(UserInput) {
                      case '1':
                        // sort according to name (in alphabetical order)
                  		qsort(Op,length,sizeof(OpAmps),&OpAmps::SortName);
                        break;
                        
                      case '2':
                        // sort according to slew rate (in increasing slew rate order)
                  		qsort(Op,length,sizeof(OpAmps),&OpAmps::SortSlewRate);
                        break;

                  The functions it passes to are this;

                  Code:
                  int OpAmps::SortName(const void *First, const void* Second)
                  {  
                    return strcmp(((OpAmps *) First)->Name, ((OpAmps *) Second)->Name);
                  }
                  
                  int OpAmps::SortSlewRate (const void *First, const void* Second)
                  {  
                    return (int) ((OpAmps *) First)->SlewRate - ((OpAmps *) Second)->SlewRate;
                  }
                  The problem is that i have the same error for both; error C2664: 'qsort' : cannot convert parameter 4 from 'int (__thiscall OpAmps::* )(const void *,const void *)' to 'int (__cdecl *)(const void *,const void *)

                  Comment

                  • AdrianH
                    Recognized Expert Top Contributor
                    • Feb 2007
                    • 1251

                    #10
                    Originally posted by ConfusedAlot
                    Im not sure...

                    I have declared all the functions within the class now, so they are all accessible to one another, in the menu system i have for example;

                    Code:
                          case '1':
                    		  Enter(OpAmpObject[database_length], database_length);
                            break;
                    I know that OpAmpObject is not defined in the class, and therefore cannot be accessed even though it is declared in main as type OpAmps, the point that is causing my main problem is what to put as the first name in the brackets above, anything i put in it does not like....
                    So you are saying that in your main you have an array of OpAmpDb called OpAmpObject? And that you want to pass (I am assuming) the last element in that array? Somehow I don’t think that is what you are intending, but I’m not sure. Please clarify, but read the following first:

                    Are you aware you are passing two (possibly different) instances of OpAmpDb to your functions Enter/Save/Load and Sort? When you call a member function that is not static, it implicitly passes the object that you are operating on. I.e.:
                    Code:
                    class A
                    {
                      int variable;
                      public:
                        void foo();
                    };
                    
                    void A::foo()
                    {
                      variable = 3;
                    }
                    
                    int main()
                    {
                      A instance;
                      instance.foo();
                    }
                    Shown in the example in the main function is the creation of an ‘A’ class object named ‘instance’. The next line calls the function foo() on that instance, thus, setting ‘variable’ in that instance to 3. And how does it do that? By passing an implicit pointer to ‘instance’ (known as the ‘this’ pointer).

                    Does that make sense?

                    So what I am saying is that those functions I referred to (Enter/Save/Load/Sort) have two instances being passed to them; the implicit one and the explicit one. Is this intentional?

                    Originally posted by ConfusedAlot
                    your right, i havent done much c++, and i get thoroughly confused as im also learning vb.net at the same time!!!
                    Well, good luck. ;)


                    Adrian

                    Comment

                    • AdrianH
                      Recognized Expert Top Contributor
                      • Feb 2007
                      • 1251

                      #11
                      Originally posted by ConfusedAlot
                      One last thing,

                      I have a sort member function that passes data to other functions;

                      Code:
                      void OpAmps::Sort(OpAmps* Op, unsigned long length)
                      
                        switch(UserInput) {
                          case '1':
                            // sort according to name (in alphabetical order)
                      		qsort(Op,length,sizeof(OpAmps),&OpAmps::SortName);
                            break;
                            
                          case '2':
                            // sort according to slew rate (in increasing slew rate order)
                      		qsort(Op,length,sizeof(OpAmps),&OpAmps::SortSlewRate);
                            break;

                      The functions it passes to are this;

                      Code:
                      int OpAmps::SortName(const void *First, const void* Second)
                      {  
                        return strcmp(((OpAmps *) First)->Name, ((OpAmps *) Second)->Name);
                      }
                      
                      int OpAmps::SortSlewRate (const void *First, const void* Second)
                      {  
                        return (int) ((OpAmps *) First)->SlewRate - ((OpAmps *) Second)->SlewRate;
                      }
                      The problem is that i have the same error for both; error C2664: 'qsort' : cannot convert parameter 4 from 'int (__thiscall OpAmps::* )(const void *,const void *)' to 'int (__cdecl *)(const void *,const void *)
                      Make the functions static:
                      Code:
                      class OpAmpDb
                      {
                      public:
                      // ...
                      	static int SortName(const void*, const void*);
                      	static int SortSlewRate(const void*, const void*);
                      //...
                      };
                      Don't use static when defining the function. I.e. this remains the same:
                      Code:
                      int OpAmps::SortName(const void *First, const void* Second)
                      {  
                        return strcmp(((OpAmps *) First)->Name, ((OpAmps *) Second)->Name);
                      }
                      
                      int OpAmps::SortSlewRate (const void *First, const void* Second)
                      {  
                        return (int) ((OpAmps *) First)->SlewRate - ((OpAmps *) Second)->SlewRate;
                      }
                      Using static will make the 'this' implict pointer not implicit. I.e. it is not passed.
                      Code:
                      class A
                      {
                      public:
                        int variable;
                        static void bar();
                      }
                      
                      void A::bar()
                      {
                        variable = 3; // invalid since A::bar() is a static function of class A.
                      }

                      Adrian

                      Comment

                      Working...