C++ Noob Class Confusion

This is a discussion on C++ Noob Class Confusion within the C++ Programming forums, part of the General Programming Boards category; Hi, I'm writing a little application using Qt, and OGL on Vista x64. The application currently works, however I'm trying ...

  1. #1
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31

    C++ Noob Class Confusion

    Hi, I'm writing a little application using Qt, and OGL on Vista x64. The application currently works, however I'm trying to learn more about C++ and this is my first project using Classes.

    I'm trying to make a Public function called "DevIL" i declare it in under Public in my GLMain class header:

    GLMain.h
    Code:
    class GLMain : public QGLWidget
    {
    	Q_OBJECT
    public:
    	GLMain(QWidget *parent = 0);
    	void DevIL();
    Then implement the function in my GLMain Class.

    GLMain.cpp

    Code:
    void GLMain::DevIL()
    {
       doSomething();
    }
    I then try and call "DevIL" or "DevIL();" or "GLMain DevIL;" from within my "open" function in "MainWindow.cpp" and i get "undeclared identifier".
    Code:
    void MainWindow::open()
     {
         QString fileName = QFileDialog::getOpenFileName(this);
         if (!fileName.isEmpty())
    	  DevIL;
    	  ilLoadImage(qPrintable(fileName));
    	 }


    Why can i only call it from within my GLMain class, and not from MainWindow. I thought public functions can be called from any others in my program. The below call of "DevIL();" works fine from my GLMain:InitializeGL function.

    Code:
    void GLMain::initializeGL()
    {
    	DevIL();
    }
    So how do i do this, Do i have to instance my class and if so any Syntax on how, as its driving me around in circles...

    Cheers!

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    DevIL is a member function, and can only be called from an object of that type (i.e. with a dot, as in object.DevIL()).

  3. #3
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Quote Originally Posted by tabstop View Post
    DevIL is a member function, and can only be called from an object of that type (i.e. with a dot, as in object.DevIL()).
    Any other hints, I did try doing similar at 2am last night for example.

    GLMain devil;
    devil.DevIL();

    I would of thought even "GLMain.DevIL();" would work why not?
    Why only from it's type? And why can i call it from Initialize GL with just "DevIL();"

    I'm afraid from your example I can't get what Object.DevIL would be in my case. Any more help or suggestions would be appreciated, As i'm sure this is meant to be easy.
    Last edited by Freestyler; 06-04-2009 at 12:31 AM.

  4. #4
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,775
    Because a class is an object, like a car. The class itself is a blueprint (it doesn't exist). So, first you must build an object from the blueprint, like building a car.
    Then you can call its members because they now exist (they've been built).

    As for the last question, because inside class "namespace", the compiler looks in both the class blueprint to see if the function exists there and it checks the global namespace - functions that are part of no class.
    So it works if the function is inside the class you're calling it from (it is the same as this->function). Otherwise you need an object to call it on.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  5. #5
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Quote Originally Posted by Elysia View Post
    So it works if the function is inside the class you're calling it from (it is the same as this->function). Otherwise you need an object to call it on.
    Thanks for the reply, So how does one create the "Car" object from the blueprint, so i can go "broom broom" globally.

    Any examples around? As i will have to do this a lot in my code so i cannot do much more until i understand it fully.

    So far i guessed my way to posting here after 48hours of frustration, I cannot seem to find any example code or tutorials, books etc that can shed any further info.

    I'm mainly using Qt4.5 for example source code. I can't seem to find much more info easily specifically other than "Public: allows calls outside the function" Which really doesn't seem to be true (well without more work than that)

    I do feel like i understand what you mean however, but i may have to read your post 20 more times for it to sink in. I will then go and search for more examples or tutorials, on how to create a car....

    Cheers!

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Post #3 has one possible solution.

    public means that you can call the function when you have an object. private means that you need to be INSIDE an existing member function to call that function. So for example, if we have:
    Code:
    class X
    {
       public:
           work()  { do_work(rand() % 100); }
       private:
           do_work(int howmuch)  { ... do work as percentage of total work ... }
    }
    ...
    int main()
    {
       ... 
       X x;
       x.work();  // legal and correct. 
       ...
       x.do_work(50); // not legal - do_work is private, we can't call it here. 
    }

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,803
    Quote Originally Posted by Freestyler
    I would of thought even "GLMain.DevIL();" would work why not?
    If your member function is static then you don't need an instance of the object to actually call the function. However, as a static function it cannot call other non-static member functions (ones that do require an instance), it can only call other member functions that are static (or other free/non-member functions).
    Code:
    class foo
    {
    public:
        static void bar();
    };
    
    void foo::bar()
    {
    }
    
    int main()
    {
       ...
       foo::bar();  // call static member function without an actual instance of class foo
       ...
    }
    "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

  8. #8
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,775
    Static functions are typically one-of-a-kind. In each instance of a Car, each one would have its own Acceleration mechanism, for example. But in this example above, we might say that all foos have one specific bar mechanism.
    And the reason a static function cannot call a non-static function is because a non-static functions belongs to an instance (like a car, a constructed car), but static functions belongs to all instances. Therefore, a static function cannot call a non-static function. How would it know which instance it belongs to, what it tries to call?

    You might want to avoid static functions until you grasp the basics of member functions.
    Remember: a blueprint is a type, and in C++, to create something of a specific type, you type the type first, then its name. You've done it before - like int x. Or in this case, it would be Car x.

    Now x is an instance of the blueprint - it is a car. So now you can access the Car's instance-specific functions by placing the name of the instance first (x in our case), then a dot (.) and lastly the function name you want to call. That's it. No more.

    Good luck.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Quote Originally Posted by matsp View Post
    Post #3 has one possible solution.

    Code:
    int main()
    {
       ... 
       X x;
       x.work();  // legal and correct. 
    }
    Thanks, I knew i was close as i can generally feel syntax causing me grief on most of this stuff.

    It did however allow me to think more conceptually about classes and OOP in general. Personally my brain likes working procedurally so it will take a bigger adjustment than i had realized until i look at it all now... So thanks for all the replies, as it was more interesting a question than i previously thought. It compiles now with:

    Code:
    void MainWindow::open()
     {
         QString fileName = QFileDialog::getOpenFileName(this);
         if (!fileName.isEmpty());
    	  GLMain GLMain;
    	  GLMain.DevIL();
    	  ilLoadImage(qPrintable(fileName));
    }
    Thanks for the in depth replies, I must now go an try and solve about 10 issues this now creates for me, which seem much more difficult to solve...

    As for const static, Yeah i did come across this issue too the other day.... I was surprised to see i couldn't initialize within the class. For example:
    Code:
    		ILuint Width, Height; // No Problems
    
            	ILuint ImgId = 0; // only static const
    
    		const static ILuint ImgId = 0; // Problems:
    "cannot convert parameter 2 from 'const ILuint *' to 'ILuint *'"

    I haven't had time to work out that issue, but in this case i only need Width, and Height to be global or public and the others can stay being initialized outside the Class. But i will likely revisit this topic and thread again sometime soon..

    Cheers,
    Scott.

  10. #10
    C++まいる!Cをこわせ! Elysia's Avatar
    Join Date
    Oct 2007
    Posts
    22,775
    A few more pointers...
    First,
    GLMain GLMain;
    GLMain.DevIL()
    This is bad, because GLMain is a type. If this compiles, it means that your instance will hide the type, so you can't create an instance of that type anymore until that variable is destroyed. Plus it creates confusion. Therefore, never name a variable the same as the type. You could name it glMain or something, or rename your class to CGLMain and CGLMain GLMain. Or something else, but don't name your variable the same as your type.

    Second:
    Code:
         if (!fileName.isEmpty());
    	  GLMain GLMain;
    	  GLMain.DevIL();
    	  ilLoadImage(qPrintable(fileName));
    You may think they are executed only if the condition !filename.isEmpty() is true, but that's not right at all. Firstly, never put a ; after an if. It makes the if a single row by itself - the compiler will ignore whatever comes after it - so it's useless by itself.
    If you remove it, then you have a single row if. That means ONLY the row right beneath it will be executed.
    To have a multi-row if, you must use { and } around the block, like so:
    Code:
         if (!fileName.isEmpty())
    {
    	  GLMain GLMain;
    	  GLMain.DevIL();
    	  ilLoadImage(qPrintable(fileName));
    }
    And also note...
    ILuint ImgId = 0; // only static const
    const static ILuint ImgId = 0; // Problems:
    ...that these variables have the same name. And you can't have two variables with the same name.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  11. #11
    Registered User
    Join Date
    Apr 2008
    Posts
    890
    Quote Originally Posted by Freestyler View Post
    Any more help or suggestions would be appreciated,
    Download Bruce Eckel's free "Thinking in C++" and start reading.

  12. #12
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Quote Originally Posted by Elysia View Post
    A few more pointers...

    Second:
    Code:
         if (!fileName.isEmpty());
    	  GLMain GLMain;
    	  GLMain.DevIL();
    	  ilLoadImage(qPrintable(fileName));
    You may think they are executed only if the condition !filename.isEmpty() is true,
    Yeah, I knew somebody would observe that I only had a few mins to test today so i just was curious about getting it compiled.. But thanks Elysia for the all of the useful info, as it was all quite helpful.

    And also note...
    ...that these variables have the same name. And you can't have two variables with the same name.
    Yeah, It was just an example... I meant i tried "ILunit ImgID" which failed because it needed const static, so i added that, and then i get the error... I will visit those issues in more depth soon however, But thankyou very much for picking up on them all.... It helps me develop good habits early on my C++ quest, and anybody else who reads the thread.

    Thanks again...

  13. #13
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Hi,

    I have another question in follow up.. I have a Qt GLMain subclass and a MainWindow subclass in my program,

    Whenever i call my class object, like mentioned previously. Eg. GLMain.cpp
    Code:
    void GLMain::DevIL()
    {
    
     QString File = QFileDialog::getOpenFileName(this);
      if (!File.isEmpty()) // Will add Error Messages later:
      ilLoadImage(qPrintable(File)); //File is "C:\test.tga"
    	Width  = ilGetInteger (IL_IMAGE_WIDTH);
    	Height = ilGetInteger (IL_IMAGE_HEIGHT);
    {
    	MainWindow FileStat;
    	FileStat.Status(); // My  "File" global get's wiped at this point.
    }
    MainWindow.cpp :When i get to "File" it's now "" empty.
    Code:
     void MainWindow::Status()
    {
    statusBar()->showMessage(qPrintable(File)); 
    }
    I seem to be wiping my global QString variable.. "File" which up until "stat.status" my global string "File" still shows "C:\test.tga" immediately after "File" shows "" or empty. But why?

    My Global is just declared at the top of MainWindow.cpp "QString File;"

    Why does it seem to wipe any reference to File when implementing the class object. And what are my solutions to stop or get around it?

    Cheers,
    Scott.

  14. #14
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,185
    Your belief that your function DevIL sets the global variable "File" in any way shape or form is incorrect. You create a new variable called "File" and never touch the global one.

  15. #15
    CNewbie
    Join Date
    Nov 2005
    Location
    Oz
    Posts
    31
    Quote Originally Posted by tabstop View Post
    Your belief that your function DevIL sets the global variable "File" in any way shape or form is incorrect. You create a new variable called "File" and never touch the global one.
    I'm basing this on debugging where i can see the value in "File" as "C:\test.tga" After my image is loaded to File in DevIL i can hover when debugging in MSVC over either the global "QString File;" or

    Code:
    statusBar()->showMessage(qPrintable(File));
    If i hover over "File" above it does show the correct "C:\test.tga" as soon as i run the "Stat.stat" all occurrences of "File" become "".

    Why do you believe my "QString File;" is not having any global affect? And what is the standard method to share the "File" data in this case between classes?

    I feel this seems to be too much of a pain to be the correct way.

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

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Creating a database
    By Shamino in forum Game Programming
    Replies: 19
    Last Post: 06-10-2007, 01:09 PM
  3. deriving classes
    By l2u in forum C++ Programming
    Replies: 12
    Last Post: 01-15-2007, 04:01 PM
  4. Need help to build network class
    By weeb0 in forum C++ Programming
    Replies: 0
    Last Post: 02-01-2006, 10:33 AM
  5. Abstract class problem
    By VanJay011379 in forum C++ Programming
    Replies: 9
    Last Post: 07-31-2002, 01:30 PM

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