Click here to Skip to main content
15,887,027 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Could anyone help me out to solve this linking error. Not sure why this happens:
Error   1   error LNK2001: unresolved external symbol "protected: virtual class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall cPlainKey::Print(void)" (?Print@cPlainKey@@MAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ)  data.obj

the code which is involved in this:
C++
#define cString std::string

class cPlainKeyDummy : public cPlainKey {
private:
  char *str;
protected:
  virtual cString Print(void);
}

cString cPlainKey::ToString(bool hide)
{
	char *tmp;
	sprintf(tmp, (hide ? "%c %.*X %s %.4s..." : "%c %.*X %s %s"),type,IdSize(),id,&PrintKeyNr(),&Print());
	return tmp;
}

cString cPlainKeyDummy::Print(void)
{
    return string(str);
}


Adding mising data:
C++
class cPlainKey : public cSimpleItem {
friend class cPlainKeys;
friend class cMutableKey;
private:
  bool au, del, super;
protected:
  virtual cString Print(void);//=0;

public:
  int type, id, keynr;

  };
class cMutableKey : public cPlainKey {
private:
  cPlainKey *real;
protected:
  virtual cString Print(void);
  virtual cPlainKey *Alloc(void) const=0;
public:
  };

class cSimpleListBase;

class cSimpleItem {
friend class cSimpleListBase;
private:
  cSimpleItem *next;
public:
  virtual ~cSimpleItem() {}
  cSimpleItem *Next(void) const { return next; }
  };


cString cMutableKey::Print(void)
{
  return real->Print();
}

cString cPlainKey::PrintKeyNr(void)
{
	char ret[16];
	sprintf(ret, "%02X",keynr);
  return string(ret);
}

int cPlainKey::IdSize(void)
{
  return id>0xFF ? (id>0xFFFF ? 6 : 4) : 2;
}


File is quite big, so I am trying to find all print()...
The code compiles fine it's just not linking.
Posted
Updated 12-Jan-12 5:30am
v5
Comments
ErnestoNet 12-Jan-12 9:55am    
If you read the linking error, the problem is
<PRE>
cPlainKey::Print(void)
</PRE>

You should post the definition of class cPlainKey to find the error.

The linker did not find the function cPlainKey::Print(). It's not present. Present is a function cPlainKeyDummy::Print() (note the 'Dummy').

If this is solved your code will crash. You are using an unitialized char pointer as argument to sprintf. The cPlainKey::str member is another possible candidate.

With warning level 4 you should see a lot of compiler warnings. You should set level 4 in the compiler options of your project. Then you will hopefully have a warning about the return values of your ToString() (cString defined, char* used) and Print() (cString defined, string used) functions.

Finally one question: Why did you use #define cString std::string?
It makes your code less readable.
 
Share this answer
 
Comments
Tomazas77 12-Jan-12 11:05am    
I used #defined cString because this code copy and paste. More simple to define than to do replacement.

Setting warning to level 4 does not add more errors, just one.
Jochen Arndt 12-Jan-12 11:16am    
Still the linker error? According to the updated question, you have a definition of the Print() member, but no implementation. And the cPlainKeyDummy::Print() implementation should generate the error ''cPlainKeyDummy': No class or namespace' if the class is not defined elsewhere.
Tomazas77 12-Jan-12 11:40am    
yes, still have linker problem
Jochen Arndt 12-Jan-12 11:46am    
And where is your implementation of cPlainKey::Print()?
Tomazas77 12-Jan-12 11:48am    
just declaration virtual in class.
I'm not sure how you get the Linker error since the above code will not compile. Where is the class definition of cPlainKey?
 
Share this answer
 
Comments
Tomazas77 12-Jan-12 11:06am    
just added to question
Jochen is correct, the linker is pointing to cPlainKey::Print() which we can't tell you if there's a problem with if (as Richard stated) you don't show us the definition of cPlainKey.

The other possible problem that may be causing this (if you DON'T have a cPlainKey::Print()) is that you have a pointer to a cPlayKeyDummy object that you're treating as a cPlainKey type and still trying to access cPlayKeyDummy::Print(). This would give you the same exact linker error.
 
Share this answer
 
C++
#define cString std::string

As has been pointed out, this #define is questionable. And it's bad style for C++. If you really need an alias, use typedef instead.
C++
class cPlainKeyDummy : public cPlainKey {

At this point we must ask: where's the definition of cPlainKey?
C++
protected:
  virtual cString Print(void);

While this may not necessarily be the case, this implies there is a virtual function of that same name defined in the base class.
C++
}

If that's the closing bracket for your class definition, you're missing a ';' here!

C++
cString cPlainKey::ToString(bool hide)

Why did you post that code? I don't see it's being used in the rest of the code you posted. Has something gone missing you meant to post as well?
C++
char *tmp;
sprintf(tmp, (hide ? "%c %.*X %s %.4s..." : "%c %.*X %s %s"),type,IdSize(),id,&PrintKeyNr(),&Print());
return tmp;

Ugh, that is wrong on so many levels ...

* First, you define a char pointer and don't initialize it.
* Then you create a string using that pointer without allocating memory first - so you're writing into an undefined memory location!
* Next, the format string you use - both of them - refer to 4 values, but then you provide 5 parameters!?
* Looking at these parameters, the last two are addresses? You didn't provide the prototype for PrintKeyNr(), but the return type of Print() is of type std::string, and address-of(std::string) is not a valid argument type you can sensibly pass to sprintf, except for printing a memory address! Of course, this consideration is moot since that is the fifth parameter which will be ignored anyway...
* Besides, what are the symbols type, id, and the function IdSize()?
* P.S.: most of the format specifiers don't make much sense to me either, e. g. 's' denotes a string and '.NN' refers to decimals of a float - so what does '%.4s' mean?

C++
cString cPlainKeyDummy::Print(void)
{
    return string(str);
}

What exactly is the function string? and what is the symbol str referring to?


We may not need all the information I asked about, but you at least have to give us some, and then copy it correctly, so we can properly parse the relevant information. Most importantly, the linker complained about a missing function implementation: std::string cPlainKey::Print(void), and that means you called it somewhere: please show us the code where you create the cPlainKey object and call the function.
 
Share this answer
 
v2
Comments
Jochen Arndt 12-Jan-12 11:24am    
Regarding your last question: The Print() function is called from within ToString().

And thanks for checking all errors in that function. I stopped analyzing after recognition of the unitialized pointer.
Stefan_Lang 12-Jan-12 11:31am    
The Print() function is called from within ToString().
Oh yeah, now that you mention it, I even referred to it myself! *laugh*
Tomazas77 12-Jan-12 11:29am    
I've just added this file so is not linked anywhere yet, but insede file is linked in cString cPlainKey::ToString(bool hide)
I can copy rest of code ("type,IdSize(),id,&PrintKeyNr()") but this should not be a problems as all of them return int.
Stefan_Lang 12-Jan-12 12:07pm    
If those are all int, then your format specifieers should be integral ones, not string! While this has nothing to do with the linker error, I suggest you rewrite that function - and before you do, read up on format specifiers!
Adding this as a new solution as this only addresses the Linker error, not all the other things I mentioned in my previous solution:

First, the linker error indicates there is no implementation for cPlainKey::Print(void). Since this function is not indicated as pure (you commented out the '=0' part), the linker will need this implementation if your code instantiates any object of cPlainKey, or a class derived from cPlainKey.

Solution
1. uncomment the '=0', i. e. make that function pure again. Is there a reason you commented that out? If so you have to fix that, not make the function concrete when it shouldn't be.
2. if you can provide a sensible implementation for cPlainKey::Print(), do that.
(you could technically do both, but it's rarely sensible to provide an implementation to a pure function and I doubt you intended that)

Second, you provided an implementation for cPlainKey::ToString(bool), but there is no such function in your class declaration!? Something isn't right there.
 
Share this answer
 
Comments
Tomazas77 12-Jan-12 11:50am    
Thanks, uncommenting =0 part solved the issue!
Great
The error is that you didn't define cPlainKey::Print.

If all the implementations of "Print" lie in derived classes, just declare it abstract (=0). If not, you must define it (even as {}).

The difference is that is you declare it as abstract, derived classes MUST provide an implementation of Print. If you define it as {}, derived classes don't need to implement Print.
It's useful when you have a lot of derived classes that don't use certain parent functions.

About the code, I agree with all said on "Solution 4". Even if the code links, it contains a lot of things to fix.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900