What's wrong with my function?

error C2228: left of '.toString' must have class/struct/union

Page 1 of 1

4 Replies - 1159 Views - Last Post: 11 December 2009 - 03:06 AM Rate Topic: -----

#1 Emzee  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 16
  • Joined: 11-December 09

What's wrong with my function?

Posted 11 December 2009 - 12:20 AM

Hey everyone. Newcomer here. I'm having an issue with my toString() function that I made for a class. I'm working on an RPG with Dark GDK (using VC++ 2008 Express), and I've just completed my header file for the player character. In the main file, I create the PlayerChar object (no-arg constructor that puts in the member fields), and then I use the toString() function to print the PlayerChar object's member fields to the console window. Here's the character.h header file:
//The Character Data
#include <sstream>
using namespace std;

class Character {
protected:
	string name;
	int level;
	int hp;
	int maxHP;
	int mp;
	int maxMP;
	int atk;
	int def;
	int intel;
	int agi;
	// DBOModel model;
public:
	Character(string aName, int aLevel, int aHP, int aMaxHP, int aMP, int aMaxMP, int aATK, int aDEF, int aIntel, int aAGI);
	Character();
	string getName();
	void setName(string na);
	int getLevel();
	int getHP();
	int getMaxHP();
	int getMP();
	int getMaxMP();
	int getATK();
	int getDEF();
	int getIntel();
	int getAgi();
	void setLevel(int lvl);
	void setHP(int h);
	void setMaxHP(int mh);
	void setMP(int m);
	void setMaxMP(int mm);
	void setATK(int ak);
	void setDEF(int de);
	void setIntel(int wis);
	void setAgi(int ag);
	//DBOModel getModel();
	//void setModel();
};

class PlayerChar : public Character {
private:
	//Tool weapon;
	//Armor arm;
	//Elemental orb1;
	//Elemental orb2;
	//Accessory access;
	bool AI_Control;
	int toNext;
	int pcEXP;
	double tempvalue;
public:
	//PlayerChar(Tool w, Armor a, Elemental o1, Elemental o2, Accessory ac, bool AIC, int nextL, int xp);
	PlayerChar();
	/*void addHP(int num);
	void addMP(int num);
	void addMaxHP(int num);
	void addMaxMP(int num);
	*/
	void levelUpNormal(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL);
	void levelUpWarrior(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL);
	void levelUpMage(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL);
	string toString();
	/*Tool getWeapon();
	void setWeapon();
	Armor getArmor();
	void setArmor();
	Elemental getOrb1();
	Elemental getOrb2();
	void setOrb1();
	void setOrb2();
	Accessory getAccessory();
	void setAccessory();*/
};

Character::Character(string aName, int aLevel, int aHP, int aMaxHP, int aMP, 
					 int aMaxMP, int aATK, int aDEF, int aIntel, int aAGI){
	name = aName;
	level = aLevel;
	hp = aHP;
	maxHP = aMaxHP;
	mp = aMP;
	maxMP = aMaxMP;
	atk = aATK;
	def = aDEF;
	intel = aIntel;
	agi = aAGI;
}

//Accessor methods
int Character::getAgi(){
	return agi;
}
int Character::getATK(){
	return atk;
}
int Character::getDEF(){
	return def;
}
int Character::getHP(){
	return hp;
}
int Character::getIntel(){
	return intel;
}
int Character::getLevel(){
	return level;
}
int Character::getMaxHP(){
	return maxHP;
}
int Character::getMaxMP(){
	return maxMP;
}
int Character::getMP(){
	return mp;
}

//Mutator methods
void Character::setAgi(int ag){
	agi = ag;
}
void Character::setATK(int ak){
	atk = ak;
}
void Character::setDEF(int de){
	def = de;
}
void Character::setHP(int h){
	hp = h;
}
void Character::setIntel(int wis){
	intel = wis;
}
void Character::setLevel(int lvl){
	level = lvl;
}
void Character::setMaxHP(int mh){
	maxHP = mh;
}
void Character::setMaxMP(int mm){
	maxMP = mm;
}
void Character::setMP(int m){
	mp = m;
}
void Character::setName(string na){
	name = na;
}

//No-Argument Constructor for PlayerChar
PlayerChar::PlayerChar(){
	name = "Luka";
	level = 1;
	hp = 1770;
	maxHP = 1770;
	mp = 453;
	maxMP = 453;
	atk = 811;
	def = 576;
	intel = 277;
	agi = 405;
	toNext = 9300;
	pcEXP = 139200;
}
//Level-up algorithm for a Normal-type Player Character (Luka, Lekori, and Lexia)
void PlayerChar::levelUpNormal(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL)
{
	level = lvl + 1;
	hp = h + (lvl * 2);
	maxHP = mh + (lvl * 2);
	mp = m + (lvl * 2);
	maxMP = mm + (lvl * 2);
	tempvalue = ak + (lvl * 1.5);
	atk = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = de + (lvl * 1.5);
	def = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = wis + (lvl * 1.5);
	def = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = ag + (lvl * 1.5);
	agi = (int)(tempvalue + 0.5);//round the value to the nearest integer
	toNext = nextL + (lvl * 12);
}
//Level-up algorithm for a Warrior-type Player Character (Sesseta and Kafua)
void PlayerChar::levelUpWarrior(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL)
{
	level = lvl + 1;
	hp = h + (lvl * 3);
	maxHP = mh + (lvl * 3);
	tempvalue = m + (lvl * 1.5);
	mp = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = mm + (lvl * 1.5);
	maxMP = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = de + (lvl * 1.2);
	def = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = ag + (lvl * 1.8);
	agi = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = wis + (lvl * 0.8);
	intel = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = ak + (lvl * 1.8);
	atk = (int)(tempvalue + 0.5);//round the value to the nearest integer
	toNext = nextL + (lvl * 12);
}
//Level up algorithm for a Mage-type Player Character (Niici)
void PlayerChar::levelUpMage(int lvl, int h, int mh, int m, int mm, int de, int ag, int wis, int ak, int nextL)
{
	level = lvl + 1;
	hp = h + (lvl * 2);
	maxHP = mh + (lvl * 2);
	mp = m + (lvl * 3);
	maxMP = mm + (lvl * 3);
	def = de + (lvl * 2);
	tempvalue = ag + (lvl * 1.5);
	agi = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = wis + (lvl * 2.5);
	intel = (int)(tempvalue + 0.5);//round the value to the nearest integer
	tempvalue = ak + (lvl * 1.5);
	atk = (int)(tempvalue + 0.5);//round the value to the nearest integer
	toNext = nextL + (lvl * 12);
}
string PlayerChar::toString()
{
	stringstream lvl, h, mh, m, mm, ak, de, wis, ag;
	lvl << level;
	h << hp;
	mh << maxHP;
	m << mp;
	mm << maxMP;
	ak << atk;
	de << def;
	wis << intel;
	ag << agi;
	string info = "Name: " + name + "\nLevel " + lvl.str() +
		"\nHeath: " + h.str() + "/" + mh.str() + "   -   Magic: " +
		m.str() + "/" + mm.str() + "\nStats: Attack - " + ak.str() + 
		", Defense - " + de.str() + "\nIntellgence - " + wis.str() + 
		", Speed - " + ag.str();
	return info;
}

And here is the main CPP file:
// Test1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <string>
#include <iostream>
//#include "items.h"
#include "characters.h"
using namespace std;

int main( int argc, char *argv[] )
{

	PlayerChar mainchar();
	cout << mainchar.toString() << endl;
	system("PAUSE");
	return 0;
}



I migrated to C++ from Java, so I have experience in dealing with objects and classes. Everything I've read so far tells me that
PlayerChar mainchar();
	cout << mainchar.toString() << endl;

should work. But I get this error:

Quote

c:\documents and settings\main\my documents\visual studio 2008\projects\test1\test1\test1.cpp(34) : error C2228: left of '.toString' must have class/struct/union

What's the deal?

This post has been edited by Emzee: 11 December 2009 - 12:29 AM


Is This A Good Question/Topic? 0
  • +

Replies To: What's wrong with my function?

#2 janotte  Icon User is offline

  • code > sword
  • member icon

Reputation: 990
  • View blog
  • Posts: 5,141
  • Joined: 28-September 06

Re: What's wrong with my function?

Posted 11 December 2009 - 12:52 AM

Why the "()" in here?
PlayerChar mainchar();

Aren't you just trying to declare an instance of PlayerChar named mainchar?

So what's with the function brackets?

EDIT: Some reading
http://www.cplusplus...torial/classes/

This post has been edited by janotte: 11 December 2009 - 12:53 AM

Was This Post Helpful? 0
  • +
  • -

#3 Emzee  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 16
  • Joined: 11-December 09

Re: What's wrong with my function?

Posted 11 December 2009 - 01:26 AM

Thanks for your reply. It is typed as such (PlayerChar mainchar(); ) because I'm using this no-arg constructor:
PlayerChar::PlayerChar(){
	name = "Luka";
	level = 1;
	hp = 1770;
	maxHP = 1770;
	mp = 453;
	maxMP = 453;
	atk = 811;
	def = 576;
	intel = 277;
	agi = 405;
	toNext = 9300;
	pcEXP = 139200;
}

And when those paratheses are removed, this error shows up:

Quote

error LNK2019: unresolved external symbol "public: __thiscall Character::Character(void)" (??0Character@@QAE@XZ) referenced in function "public: __thiscall PlayerChar::PlayerChar(void)" (??0PlayerChar@@QAE@XZ)
1>C:\Documents and Settings\Main\My Documents\Visual Studio 2008\Projects\Test1\Debug\Test1.exe : fatal error LNK1120: 1 unresolved externals

I should point out that PlayerChar is a derived class of Character, and PlayerChar's constructor's first 10 variable initializations (name through agi) are from the Character class (which is not abstract, btw). That's all in the code block I posted before, in character.h.

EDIT: I did some tinkering to make my code more conventional for C++. More specifically, I put the constructors part of the actual class definitions, as opposed to making them function prototypes. It turns out that that fixed the problem.

This post has been edited by Emzee: 11 December 2009 - 01:55 AM

Was This Post Helpful? 0
  • +
  • -

#4 Oler1s  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1395
  • View blog
  • Posts: 3,884
  • Joined: 04-June 09

Re: What's wrong with my function?

Posted 11 December 2009 - 03:03 AM

Quote

It is typed as such (PlayerChar mainchar(); ) because I'm using this no-arg constructor:
You want to use the 0 parameter constructor, sure, but you have the syntax all wrong. A look at the link janotte gave you would have helped. C++ isn't Java. There are syntactical differences.

PlayerChar mainchar(); declares a function called mainchar that takes no arguments and returns a value of type PlayerChar. That's not what you want.

Quote

And when those paratheses are removed, this error shows up:
So understand what the error is saying. Don't fiddle with parens, brackets, etc. hoping the errors go away and everything magically works out.

Quote

EDIT: I did some tinkering to make my code more conventional for C++. More specifically, I put the constructors part of the actual class definitions, as opposed to making them function prototypes. It turns out that that fixed the problem.
Probably because in your changes, you added in the definition for the 0 parameter constructor of Character.

From your original code:

public:
	Character(string aName, int aLevel, int aHP, int aMaxHP, int aMP, int aMaxMP, int aATK, int aDEF, int aIntel, int aAGI);
	Character();



See, you declare that you have a constructor for Character that takes no arguments. Fine. But when you link all the code together to form an executable, the linker can't find the definition.

That's what the error message is telling you: unresolved external symbol "public: __thiscall Character::Character(void). It's saying that there exists this function Character::Character(), but it can't find the definition (can't resolve it).
Was This Post Helpful? 0
  • +
  • -

#5 Bench  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 856
  • View blog
  • Posts: 2,339
  • Joined: 20-August 07

Re: What's wrong with my function?

Posted 11 December 2009 - 03:06 AM

Welcome to one of the more subtle parsing rules in C++.
class myclass {};

int main()
{
    myclass foo = myclass();
    myclass bar();  //What is 'bar' ??
} 
You might think that both of these statements create myclass objects using the default constructor; the first one is OK - using copy-assignment, but the second one is in fact a function. Actually, if you read this link, you'll see - it gets worse

C++ inherited its syntax rules from C, which doesn't deal with constructors, so C++ is forced to treat myclass bar(); as a function declaration, otherwise forward-declarations of zero-argument functions would be ambiguous.

The solution is to omit the parenthesis whenever you're not passing arguments to a non-default constructor
class myclass {};

int main()
{
    myclass foo = myclass();
    myclass bar;  //That's better
} 

This post has been edited by Bench: 11 December 2009 - 03:07 AM

Was This Post Helpful? 0
  • +
  • -

Page 1 of 1