Problem With Virtual Function & Abstract Class

Pages: 12
In a console game I've been working on where you play a fighter and kill monsters, I got everything to work, but I wanted to make it more interesting. I tried to add a virtual "attack" function to the Monster base class and an overrider in each of the monster derived classes so that the implementation of a separate generic function could be called in different ways and different numbers of times depending on the monster, but attempting to compile gives me (what appear to be) completely nonsensical errors, like identifiers not being defined when they are, or functions not taking a certain number of arguments when they do. I've looked over everything for the last few days trying to figure this out, and I just can't. Any help would be fantastic.

Here's some of my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Base Class, In classList.h

class Monster {

	// Monster Data Members ...

public:
	// Virtual Attack Function
	virtual void atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier) {
		monAtk(pfighter, pMonster1, monWpn, fMultiplier);
	}
	
        // Other Member Functions ...
};


// Derived Class

class Hydra : public Monster {

public:

	void atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier) {

		std::cout << "\nThe first head strikes!\n";
		monAtk(pfighter, pMonster1, monWpn, fMultiplier * 1.2, 0.4);

		std::cout << "\nThe second head strikes!\n";
		monAtk(pfighter, pMonster1, monWpn, fMultiplier * 1.2, 0.4);
	}
};


The thing that gets me is that everything worked before I added the "virtual" function, and now I'm getting a bunch of compile errors, and I haven't been able to figure out why. The same few errors come up for each call to atk(), like these:
"C2061 syntax error: identifier 'Weapon'"
"C3861 'monAtk': identifier not found"

I should probably also say that when I try to make "atk()" a pure virtual function, I get errors saying that the derived classes are also abstract classes. Any ideas as to what might be wrong here?
Just to clarify, are you saying that all you do is add the keyword virtual and the code no longer compiles, but if you remove it it compiles fine?

Usually cascading compiler errors happen for one of a few reasons:
* You forgot the semicolon at the end of a class definition.
* You left a curly brace unclosed, which caused the compiler to get severely confused.
* You made a typo in a typedef or using declaration, which caused much of the following code to become meaningless (if the compiler doesn't know if an identifier is an object, a type, or a function then it can't parse the code).
No, that's not all that happened, I just wasn't sure how much info was necessary. There is another function which was used to call "monAtk()", but that call has now been replaced with "pMonster1->atk( ... )", and the "atk()" function is completely new, both virtual and overrider. "atk()" just serves the purpose of allowing me to call "monAtk()" in different ways for different monsters, as I showed in my above code. But if I change it back, removing all "atk()" functions and replacing the call to it with "monAtk()", it should work like it did before.

I double checked all arguments and parameters, so I know there isn't a discontinuity anywhere in passing in the arguments. My IDE isn't giving me any errors like a missing ";" or "}", and I haven't used a typedef or using declaration.
Is this:
"C2061 syntax error: identifier 'Weapon'"
the earliest error the compiler throws at you? If so, it could simply mean you forgot to include the header that declares that type.
Yes, it is the first error. I wish a missing #include was the problem, that would be easy to fix. But I haven't added any new headers since the last successful compilation, and i just double checked, and the header this declaration is in is already #included in the main source file.

EDIT: If it helps, that first error is thrown in the definition of "atk()" inside "Monster"
Last edited on
But is it included before Monster is defined?
Monster is declared in "classList.h" and defined in "classList.cpp". All other necessary functions are declared and defined in a separate header and source file, and that header is also #include d in "classList.h" using #pragma once , and both of these headers are #include d in the main source file after the standard #include s.
Hm... Then I'd have to see the code. Could you upload it to Github or somesuch?
Also post the exact errors from the compiler.
Last edited on
DropBox is the best I could do:
https://www.dropbox.com/sh/vx6zku5vvvhb2sn/AADz0rQUReYdGNUgVGx4T8iha?dl=0


All of the errors are these, repeated 300+ times in different places:

classList.h(76,66): error C2061: syntax error: identifier 'Weapon'
classList.h(77,31): error C2065: 'monWpn': undeclared identifier
classList.h(77,39): error C2065: 'fMultiplier': undeclared identifier
classList.h(77,3): error C3861: 'monAtk': identifier not found
classList.h(95,58): error C2061: syntax error: identifier 'Weapon'
classList.h(96,31): error C2065: 'monWpn': undeclared identifier
classList.h(96,39): error C2065: 'fMultiplier': undeclared identifier
classList.h(96,3): error C3861: 'monAtk': identifier not found

EDIT: Also, I apologize, my code looks rough and there isn't a lot of commenting or white space, so it's probably fairly difficult to read... I never really planned on taking as far as i have, or sharing it, so I totally understand if you don't care to sift through all of that. I can try to clean it up and re-upload to the DropBox though.
Last edited on
Well, the problem is quite clear. You're defining Weapon on line 339 of classList.h, but you use it for the first time on line 76. It looks like Weapon and its subclasses don't depend on Monster, so you can simply move all of those up.
Hm... well, now I feel kind of dumb. Thanks helios for taking the time to look at that. That fixed all the errors except one, and it's saying "monAtk: identifier not found", I'm guessing for the same reason as above. I tried moving things around to get a definition of "monAtk()" before the call, but that's proving difficult, as I'm getting more cascading errors like before. Might adding a separate source/header just for the attack functions be sensible? I'm thinking that if I do that, I can include "fighterFns.h" in the new header, and then include the new header in "classList.h"

EDIT: Well, i did that, and I'm finding a whole slew of new cascading errors...
Last edited on
The problem is that you're putting function definitions in headers. That can work if your code doesn't contain mutual dependencies, or if the functions are really simple, but otherwise you get into unresolvable error territory.
Move all the function (including member function) definitions in classList.h and fighterFns.h to their corresponding .cpps.
classList.h|96|error: 'monAtk' was not declared in this scope|

monAtk isn't a member of class Monster, so you can't all it like this.
To which class does it belong to?

classList.h|76|error: 'Weapon' has not been declared|

You need to put Weapon above Monster

These are the 2 main errors, they just appear at different places
@helios THANK YOU!! I had to sacrifice my use of default arguments in order to get all the function definitions into the .cpp files without any errors, but it finally compiled successfully!! Thanks much!
You can use default arguments with separately declared functions.
1
2
3
4
5
6
7
void foo(int bar = 0);

//...

void foo(int bar){
    //...
}
How do you mean?

I have:
1
2
3
4
5
6
7
8
9
10
11
12
// fighterFns.h
void monAtk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier, float fSplitPoint, int nOverage);

// fighterFns.cpp
void monAtk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier, float fSplitPoint, int nOverage) {
	// code...
}

// classList.cpp
void Goblin::atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier) {
	monAtk(pfighter, pMonster1, monWpn, fMultiplier, 0, 0);
}


How would I change this do what you're suggesting?
Okay, new problem... None of the derived classes are overriding the base class virtual function, and I'm not sure why. Here's what I have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// classList.h
class Monster {

	// Monster Attributes...

public:

	// Monster Methods
	virtual void atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier) = 0;
};


class Goblin : public Monster {
public:
	
	void atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier);
};

// classList.cpp
void Goblin::atk(Character* pfighter, Monster* pMonster1, Weapon* monWpn, float fMultiplier) {

	monAtk(pfighter, pMonster1, monWpn, fMultiplier, 0, 0);
}


The code compiles and executes, but crashes when it makes a call to "atk()", so I can only guess that the virtual function isn't being overridden. Can anyone explain why this is happening?
Last edited on
Have a look at the override keyword.
https://en.cppreference.com/w/cpp/language/override
I just tried both "override" and "final" in the derived class member function declarations, with both a virtual and pure virtual parent function, and the program still is only calling the parent function (it crashes when the parent function is pure virtual).
Is the code on dropbox the latest one ?
Pages: 12