I have limited experience with Object Oriented coding but not programming in general.
Here is a stripped down version of my code. What I'm trying to do is set a variable declared in 'CProjectView::Handler' using a function in 'CtestClass'. Simple enough! but not for me.

In the code as shown, testClass.cpp compiles with no errors, but projectView complains about a 'non-static' function. So I add 'static' to the function in testClass.h. Now testClass.cpp complains about a 'non-static' variable. So I add 'static' to the variable.

Bingo! Everything compiles without error.
BUT now when I try to 'link' this lot, I get an "unresolved external symbol...." error.

What am I doing wrong?

//// projectView.h
class CProjectView : public CView {
protected:
  CProjectView();
public:
  void Handler();
};
//// projectView.cpp
CProjectView::CProjectView() {  // constructor
}
void CProjectView::Handler() {
  int viewData;  // trying to set this value.
  if (CTestClass::aFunction(&viewdata)) {
    ...
  } else { ... }
}

//// testClass.h
class CTestClass {
public:
  CTestClass()
  bool aFunction(int*);
private:
  int varB;
};
//// testClass.cpp
CTestClass::CTestClass() {  // constructor
  varB = 555;
}
void CTestClass::aFunction(int *testdata) {
  *testdata = anotherFunction(varB);
}

Dani AI

Generated

Two separate, common C++ gotchas are colliding in this thread: (1) static vs instance members/definitions and (2) printing MFC CString objects with std::cout. was right that declaring something static changes linkage and requires a single out‑of‑class definition; discovered that creating an instance (and letting the destructor run) is usually the simplest, correct approach when the state belongs to an object.

Practical rules to apply:

  • If a method needs per‑object data (like varB), make it an instance method and call it on an object. Avoid naming the variable the same as the type (use CTestClass obj(555); or CTestClass socket(555);), and don’t use the TypeName TypeName(); form — that’s parsed as a function declaration (the “most vexing parse”).

  • If you do make a data member static, you must provide one definition in a single .cpp file, for example:

    // in testClass.cpp
    int CTestClass::varB = 555;

    Also ensure your header and implementation signatures match exactly (return type, parameters, static qualifier).

Why you saw an address instead of the string: in typical Unicode MFC builds CString converts to wchar_t*. std::cout has no overload for wchar_t*, so it falls back to printing a pointer value. Fixes include using std::wcout or converting to a narrow string before streaming. Examples:

std::wcout << static_cast<LPCWSTR>(socketResponse) << '\n';

or

CStringA ansi(socketResponse);          // convert to ANSI
std::cout << (LPCSTR)ansi << '\n';

Other tips: use TRACE/AfxMessageBox for quick MFC debugging, watch UNICODE vs ANSI throughout the project, and prefer instance methods unless you explicitly want class‑wide state.

Recommended Answers

All 5 Replies

This is normal c++ stuff and has nothing at all to do with MFC, other than MFC is also c++. When you put static keyword in the .h file that is making it global with the namespace of the class in which it is defined. So your compiler is producing unresolved error because you didn't actually create an object of that static variable.

you didn't say what variable you made static, so I'll just assume it is named "var". Put this at (or near) the top of the implementation file (*.cpp) -- outside any function, just like you would any other global variable.

CProjectView::var = 0;

I probably did not explain that right...

The problem comes when I want to call 'aFunction()', which uses varB internally, in the CProjectView::Handler(). I get a compile error if aFunction is non-static and a Link error if it's static.

That said, here's how I solved the problem...

void CProjectView::Handler() {
  CTestClass  CTestClass(555); // create an instance of CTestClass
  // modified to parse the variable
  
  int viewData;  // trying to set this value.
  if (CTestClass.aFunction(&viewdata)) {  // '.' operator instead of '::' 
    ...
  } else { ... }
}

Function and Variable non-static.
This also gave me the added advantange of being able to use the CTestClass destructor for clean up when exiting the Handler function.

One interesting thing which you can surely explain...
If I used the following it would NOT create an instance...
CTestClass CTestClass();

But if I parse a variable, an instance was created.
CTestClass CTestClass(555);

Ancient Dragon,
I'm having problems and really need some help. Would you have any interest in helping me out off-line? Please PM me and, if yes, I'll explain further.

CTestClass CTestClass();

The above is not an instance of a CTextClass class but a prototype for a function that returns a CTestClass object.

Please PM me

No. Post your questions so others can learn or answer. I don't do unpaid private tutoring (well, actually, I don't do paid private tutoring either.)

No. Post your questions so others can learn or answer.

:) I posted an almost word-for-word response on another board.

OK! This is what drives me nuts!
I have a 'Socket class' with a public variable - CString response.

In a 'Control class' I have the following function...

bool CASControl::Login(CString userid, CString passwd) {
  CString		IP = "xx.xx.xx.xx";
  int			port = xx;
  CString		keys;
	
  CASSocket	CASSocket(IP,port);
  if (!CASSocket.getKeys(userid,passwd)) {
    MessageBox(NULL,CASSocket.response,NULL,0);
    return false;
  } 

  MessageBox(NULL,CASSocket.response,NULL,0);

  // this seems to return a pointer address 	
  keys = CASSocket.response;
  std::cout << "In Ctrl: " << keys << "\n";	 

  return true;
}

The Socket is working and gives the correct response which I can see in the 'Message box', but when I try to assign that to 'keys' I get an address - not the data.

I plan to return the response to yet another class by reference (not shown here)

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.