CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 14 of 14
  1. #1
    Join Date
    Jun 2011
    Posts
    30

    C++ extern question

    MFC application.
    I created a file access class for simple debug stuff that's not needed to run thru the document's serialize. I want to be able to call it from anywhere or any class, so I figured I can just put it global in the app's header file right under the theApp object. I used VC 6 in the past and I don't remember seeing the extern in front of the theApp object. Now I'm using VC 2005 and the project created the app object with extern.

    I assume I should create my class object with extern also ?
    What is the difference in a global object with or without extern ?

    ----In my app's header file--
    extern CViewSwitchApp theApp;
    extern MyFileClass FileClass;
    ----------------------------
    Last edited by J_W; May 9th, 2013 at 06:10 PM. Reason: spelling

  2. #2
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: C++ extern question

    Instead of making it global, why not make it a member of your CWinApp derived class? Then you can access it anywhere by calling AfxGetWinApp().

  3. #3
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Quote Originally Posted by Arjay View Post
    Instead of making it global, why not make it a member of your CWinApp derived class? Then you can access it anywhere by calling AfxGetWinApp().
    Thanks you are right. (I will research my original question of "extern" later in the docs.)
    I will now try your get the pointer method above.

    I had already had trouble with my previous attempt and then tried a somewhat straight approach before seeing your post, but I got a link error.
    Code:
    class CViewSwitchApp : public CWinApp
    {
    public:
    	CViewSwitchApp();
     //----added by me----//
     MyFileClass FileClass;   // CREATE INSTANCE OF MY FILE CLASS //
     //--end added by me--//
    
    // Overrides
    public:
    	virtual BOOL InitInstance();
    
    // Implementation
    	afx_msg void OnAppAbout();
    	DECLARE_MESSAGE_MAP()
    };
    
    extern CViewSwitchApp theApp;
    
    =========================================
    then from another view I tried calling it like this
    -------
    
    
    void CViewSwitchView::OnViewCall()
     { 
       if (!theApp.FileClass.FileWriteTextOut("TestFileOut.txt", 
              "\nWhatever text out\n another line\n and yet another line\n") )
          return;
      // else other code if needed
     
     } // end of OnViewCall func
    But I'm getting a ViewSwitchView.obj : error LNK2019: unresolved external symbol "public: bool __thiscall MyFileClass::FileWriteTextOut(char const *,char const *)" (?FileWriteTextOut@MyFileClass@@QAE_NPBD0@Z) referenced in function "public: void __thiscall CViewSwitchView::OnViewCall(void)" (?OnViewCall@CViewSwitchView@@QAEXXZ)

    Obviously I'm screwing up. as said earlier I am a part time novice.

  4. #4
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,395

    Re: C++ extern question

    Did you implement the MyFileClass::FileWriteTextOut(char const *,char const *) method?
    Victor Nijegorodov

  5. #5
    GCDEF is offline Elite Member Power Poster
    Join Date
    Nov 2003
    Location
    Florida
    Posts
    12,635

    Re: C++ extern question

    What does your class do that CStdioFile doesn't?

  6. #6
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Quote Originally Posted by VictorN View Post
    Did you implement the MyFileClass::FileWriteTextOut(char const *,char const *) method?
    Yes I did in the MyFileClass.cpp file.
    *later update edit-> Opps just saw my stupid error thank you so much for jogging my dumb inexperienced mind.
    See code fix inserted. Ahhhhhh what a stupid miss. Thanks much to VictorN for asking the redundant question, he was spot on at spotting my foobar ability.
    I'm all fixed up now, can use ptr or just call the theApp. I will study up on the original extern question, but it's a mute issue now since the way I originally tried it had some problems.
    Code:
    #include "stdafx.h"
    #include "MyFileClass.h"
    #include <fstream>
    
    MyFileClass::MyFileClass(void)
     { }
    
    MyFileClass::~MyFileClass(void)
     { }
    !!!! Update !!!
    bool FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut) <- the problem
    bool MyFileClass::FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut)<- the fix
     {
       std::fstream FileObj;           
       FileObj.open(StrgLiteralFilename, std::fstream::in | std::fstream::out | std::fstream::app); 
       if (!FileObj.is_open() ) { ::MessageBox(NULL, "Check code to see why file failed to open", 
      "Error, opening the file", MB_OK); return false; }
       FileObj << StrgLiteralTextOut;
       FileObj.close(); 
       return true;
     }
    and of course in the MyFileClass.h file I have
    Code:
    #pragma once
    
    class MyFileClass
     {
     public:
      MyFileClass* pMyFileClass;
      MyFileClass(void);
      ~MyFileClass(void);
    
      bool FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut);
     };
    Quote Originally Posted by GCDEF View Post
    What does your class do that CStdioFile doesn't?
    Nothing really, in fact all my class does is make calls to an fstream object. I like it because I can just throw in one line of code with the two arguments anywhere I want. I like it better than trace macros, but that's just me.
    Last edited by J_W; May 10th, 2013 at 10:36 AM. Reason: Added some code

  7. #7
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: C++ extern question

    Code:
    bool MyFileClass::FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut)
     {
       std::fstream FileObj;           
       FileObj.open(StrgLiteralFilename, std::fstream::in | std::fstream::out | std::fstream::app); 
       if (!FileObj.is_open() ) { ::MessageBox(NULL, "Check code to see why file failed to open", 
      "Error, opening the file", MB_OK); return false; }
       FileObj << StrgLiteralTextOut;
       FileObj.close(); 
       return true;
     }
    For the definiton of FileWriteTextOut, you haven't stated that it's a member function of the class MyFileClass.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Quote Originally Posted by 2kaud View Post
    Code:
    bool MyFileClass::FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut)
     {
       std::fstream FileObj;           
       FileObj.open(StrgLiteralFilename, std::fstream::in | std::fstream::out | std::fstream::app); 
       if (!FileObj.is_open() ) { ::MessageBox(NULL, "Check code to see why file failed to open", 
      "Error, opening the file", MB_OK); return false; }
       FileObj << StrgLiteralTextOut;
       FileObj.close(); 
       return true;
     }
    For the definiton of FileWriteTextOut, you haven't stated that it's a member function of the class MyFileClass.
    YES! Thank you, I spotted it myself as soon as I posted it, Yea right! you are probably saying. But as soon as I looked it on the forum my mind woke up. Thanks to VictorN and you both.

  9. #9
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: C++ extern question

    @J_W, glad you have this figured out.

    Not that it matters, but you might consider using the TCHAR form of strings so the app can be compiled in UNICODE in the future without a bunch of refactoring.

    For example:
    Code:
    bool MyFileClass::FileWriteTextOut(const char* StrgLiteralFilename, const char* StrgLiteralTextOut)
    can be declared as
    Code:
    bool MyFileClass::FileWriteTextOut(LPCTSTR StrgLiteralFilename, LPTSTR StrgLiteralTextOut)

  10. #10
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Good point Arjay, actually I used to use TCHAR all the time, but some folks seem to think it a performance hit (in some scenarios of Unicode compiles) and lean towards just making two separate explicit defines. I don't have enough experience to really have an opinion on that myself.

    However for my quick debug stuff it's all gonna be Asci txt anyhow.

    BTW I did find the answer to my original extern question (at least I think I understand it)
    static gives global access within code file scope.
    extern gives global access and linkage across all files in a project.

    However I thought any class or variable implementated outside any block already had global linkage ? Anyhow I kinda understand it now. What got me curious is,
    VC ver 8 in a MFC appwizard generation puts theApp object with an "extern" in the header file and without in the cpp implementation file.
    VC ver 6 in a MFC appwizard generation simply does not put the theApp object in the header file at all, and just puts it in the cpp file as ver 8 does.

  11. #11
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: C++ extern question

    Quote Originally Posted by J_W View Post
    Good point Arjay, actually I used to use TCHAR all the time, but some folks seem to think it a performance hit (in some scenarios of Unicode compiles) and lean towards just making two separate explicit defines. I don't have enough experience to really have an opinion on that myself.
    What many folks forget is that Windows stores it's strings as UNICODE (well, on NT based Windows, not 9x systems). So if you compile your program for ANSI, each string call made to the OS gets converted to/from ANSI/UNICODE. So some folks talk about the performance hit of using a longer UNICODE string, but fail to take the ongoing conversions into account when running an ANSI app on a UNICODE system.

    What has worked well for me is to compile the char set of the app to the OS I was running in (in 9x, that was ANSI, and now on NT,Win7/8 it's UNICODE) and isolate string conversions to the layer that deals with any external string data. So if my app is targeted to Win7, all my strings will be in UNICODE within the app and if I'm reading or writing to a file that needs to be in ansi, I convert immediately before I write the file and convert after I need to read the file. Similar for a socket, if the data is coming in as ANSI, I convert to UNICODE before I use it in my program. I like this approach because I only have a couple of places in my code where I do any string conversions.

    I've seen other approaches where folks are doing back and forth string conversions all through out their code and it makes it tough to debug and maintain code like this.

    Quote Originally Posted by J_W View Post
    BTW I did find the answer to my original extern question (at least I think I understand it)
    static gives global access within code file scope.
    extern gives global access and linkage across all files in a project.
    That is correct.

  12. #12
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Quote Originally Posted by Arjay View Post
    What many folks forget is that Windows stores it's strings as UNICODE (well, on NT based Windows, not 9x systems). So if you compile your program for ANSI, each string call made to the OS gets converted to/from ANSI/UNICODE. So some folks talk about the performance hit of using a longer UNICODE string, but fail to take the ongoing conversions into account when running an ANSI app on a UNICODE system.
    Well that's an aspect I've never realized before.

    What has worked well for me is to compile the char set of the app to the OS I was running in (in 9x, that was ANSI, and now on NT,Win7/8 it's UNICODE) and isolate string conversions to the layer that deals with any external string data. So if my app is targeted to Win7, all my strings will be in UNICODE within the app and if I'm reading or writing to a file that needs to be in ansi, I convert immediately before I write the file and convert after I need to read the file. Similar for a socket, if the data is coming in as ANSI, I convert to UNICODE before I use it in my program. I like this approach because I only have a couple of places in my code where I do any string conversions.

    I've seen other approaches where folks are doing back and forth string conversions all through out their code and it makes it tough to debug and maintain code like this.
    I tend to agree with that logic in as much as I can encompass the whole of it.
    Last edited by J_W; May 10th, 2013 at 05:10 PM. Reason: typo

  13. #13
    Arjay's Avatar
    Arjay is offline Moderator / EX MS MVP Power Poster
    Join Date
    Aug 2004
    Posts
    13,490

    Re: C++ extern question

    Quote Originally Posted by J_W View Post
    I tend to agree with that logic in as much as I can encompass the whole of it.
    The gist of this approach is:
    1. Use TCHAR string forms throughout the app (e.g. LPCTSTR, LPTSTR, instead of char*)
    2. Use the _T("") macro for hard coded string literals (e.g. _T("hard coded string") instead of "hard coded string").
    3. Compile the app for the OS. For WinNt and above, use UNICODE
    4. For any external data (both incoming and outgoing), create a conversion layer and convert any incoming/outgoing string data in one place.

  14. #14
    Join Date
    Jun 2011
    Posts
    30

    Re: C++ extern question

    Quote Originally Posted by Arjay View Post
    The gist of this approach is:
    . . . . . . .
    Thanks I stored that info on my drive. BTW what's your input on using fstream etc C++ stream classes with wchars. I've read in the past that you have to always open the file in binary mode and work the array to deal with whether the file is stored little endian or Big. Anyhow no biggy just if you want to comment on that.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured