Several questions has been asked related to this error, but each one of them practically relates to the object or type in question not declared before usage. For example:
class A
{
public:
A_Object a_obj;
};
Getting the error A_Object was not declared in this scope means A_object is not declared anywhere within the file.
NOTE: This is my understanding of the error.
Now I have a file called Account.h as shown below:
#ifndef ACCOUNT_H_
#define ACCOUNT_H_
class Account
{
//fields and methods
};
#endif /* ACCOUNT_H_ */
I also have a second file called Address.h as shown below:
#ifndef ADDRESS_H_
#define ADDRESS_H_
#include "Account.h"
typedef Account account_type;//Error here
class Address
{
//Fields and methods
};
#endif /* ADDRESS_H_ */
When I try to compile this file I get the error Account was not declared in this scope.
Any Ideas why?
Does Account.h actually also include Address.h? Such a circular reference seems the most likely situation.
Do you have a matching #endif at the end of both include files?
First point, your understanding about A_object is incorrect, the error means that A_object was not declared prior to it's first use, not that it wasn't declared anywhere.
Second point, the code you posted is incorrect, because you are missing #endif from both files. But assuming that was the only missing code then you would not get the error you describe. Post the real code that has the error.
I've seen this error when Address.h includes Account.h, which includes OtherFile.h, which includes Address.h. Is it possible you have a circular dependency? It may be hard to find.
This might be a case where a more core understanding of how the c/c++ compiler works would be in order. Include blocks, forward declarations, includes etc. All of these concepts did not make sense to me until I understood the basics of how compiler works. While I realize that this is somewhat of an oversimplification of compiler theory / logic, bear with me.
One of the first steps that a c++ compiler performs is a pre-processing (pre-compiler) step where it takes all of the files that are required, and combines them into one big flat file. In "C" languages, these pre-compiler operations a denoted using the hash (#) symbol. All an "#include" is doing, is directing the pre-compiler to bring this file into the entire "flat-file". If you have a cyclic include, your pre-compiler will get into an infinite loop and blow up, or say something super generic and useful like "the symbol has already been defined".
Include blocks, forward declarations, and all of the neat things that you are taught in c++ books that say "just do it, trust me" generally are helping you to avoid these type of compiling problems.
Related
I have a large project which is designed to control and test hardware.
There are 4 device control classes (for interferometers, a piezo-motor, a PXI system, and a nano-positioning controller).
I created a "master" class called MainIO which stores an instance of each of the above classes, in order to perform operations across the range of IO (i.e. move motor and check interferometers). The MainIO header file includes the 4 control classes headers.
I then have a separate "global" hpp/cpp which contains global variables, conversions, ini file operations and so on. This is laid out with namespaces for the types of operation rather than creating a class, i.e. GCONV::someFunction(); and GMAIN::controllerModel;
I need all 4 control classes to have access to conversion and other global operations. I had them all including global.hpp at one point, but I've changed something (I can't think what it could be!) and now it seems that I cannot include global.hpp in ANY of my control class hpp's or cpp's without getting a linker error -
global.obj:-1: error: LNK2005: "class QString GMAIN::controllerModel" (?controllerModel#GMAIN##3VQString##A) already defined in controllers.obj
I'm absolutely certain that I've done something stupid and the solution is staring me in the face, but it's got to the stage where I'm getting so frustrated with it that I cannot see the wood for the trees.
I have discovered what I was doing wrong, and although it is frustratingly simple, it took me a while to find the relevant documentation to discover my error, and so I will answer my own question in the hope of giving someone else an easier time.
It turns out that in global.hpp I was declaring variables within a namespace like this:
namespace GMAIN {
QString controllerModel;
}
Essentially this means that every file that includes global.hpp will include its own definition of QString controllerModel thereby throwing the linker error. Each control class would have its own definition of the same named variable, violating the one definition rule.
To fix this, QString controllerModel needs to be extern'ed. The extern keyword allows a variable to be declared in multiple locations while only having a single definition (and hence not breaking the rule).
So the working code is now:
//in global.hpp
namespace GMAIN {
extern QString controllerModel; //declaration - this is called for each `#include global.hpp`
}
//in global.cpp
namespace GMAIN {
QString controllerModel; //definition - only called once as .cpp is never included
}
Are you defining controllerModel where you should only be declaring it?
http://www.cprogramming.com/declare_vs_define.html
You should export your dll.
Use __declspec(dllexport). You can include __declspec(dllexport) as a macro in your header file and put the macro in the beginning of each and every member function.
For example:
In your Header.h file include
#define MYMACRO __declspec(dllexport);
and in your class
class classname
{
public:
MYMACRO void MYFUNCTION();
MYMACRO void MYFUNCTION2();
};
I am getting this compiler error
error: 'RawLog' does not name a type
Here is the relevant code:
//DataAudit.h
#ifndef DATAAUDIT_H
#define DATAAUDIT_H
class RawLog;
class DataAudit
{
...
private:
RawLog* _createNewRawLog(); // This is the line indicated with the error
};
#endif // DATAAUDIT_H
Usually a forward declaration resolves this kind of error. This answer indicates that a circular header inclusion may cause this. But doesn't the use of the #ifndef and #define statements prevent circular header inclusion?
Is there another reason I might see this error?
What are some avenues of approach I could use to further deduce the nature of this error?
Update: This is rather odd. I have a Globals.h file, and if I define a new enum in Globals.h, the error appears. Then if I comment out the enum, the error goes away. This leads me to think that the circular dependency has existed for a while, and adding the enum somehow re-orders the compilation units, thus exposing the dependency that wasn't there before?
The #ifndef header guard doesn't prevent circular dependencies. It just prevents multiple inclusions of the same header in a single file.
Looks like a circular dependency to me. This means you #include a header in DataAudit.h that #includes DataAudit.h either directly or indirectly.
In the end, I am not sure I understand completely why the error occurred, but this is what I did to resolve it, and some other related information. Maybe this will help others that come across this question.
For each header file in my project
For each #include "..." in the header
If there are no references to the class in the #include, remove it.
If there are only pointers to the class defined in the #include, then replace it with a class ... forward declaration.
If there is a member instance of the class defined in #include and it makes sense to use a pointer and allocate the member on the heap, then change the member to a pointer, and replace the #include with a class .... forward declaration.
Go through my Globals.h and move anything that can be moved out of it to more localized and specific header files.
Specifically, remove an enum that was defined is Globals.h, and place it in a more localized header file.
After doing all this I was able to make the error go away. Strangely enough, the enum in Globals.h seemed to be a catalyst for the error. Whenever I removed it from Globals.h, the error would go away. I don't see how this enum could cause the error, so I think it indirectly led to the error somehow. I still wasn't able to figure out exactly how or why, but it has helped me for this guideline when coding in C++:
Don't put anything in a header file unless it needs to be there. Don't
place anything in a Globals.h that can be placed in a more localized
file. Basically, do all you can to reduce the amount of code that is
included through the #include directives.
I'm pretty clear on when I can/can't use forward declaration but I'm still not sure about one thing.
Let's say I know that I have to include a header sooner or later to de-reference an object of class A.
I'm not clear on whether it's more efficient to do something like..
class A;
class B
{
A* a;
void DoSomethingWithA();
};
and then in the cpp have something like..
#include "A.hpp"
void B::DoSomethingWithA()
{
a->FunctionOfA();
}
Or might I as well just include A's header in B's header file in the first place?
If the former is more efficient then I'd appreciate it if someone clearly explained why as I suspect it has something to do with the compilation process which I could always do with learning more about.
Use forward declarations (as in your example) whenever possible. This reduces compile times, but more importantly minimizes header and library dependencies for code that doesn't need to know and doesn't care for implementation details. In general, no code other than the actual implementation should care about implementation details.
Here is Google's rationale on this: Header File Dependencies
When you use forward declaration, you explicitly say with it "class B doesn't need to know anything about internal implementation of class A, it only needs to know that class named A exists". If you can avoid including that header, then avoid it. - it's good practice to use forward declaration instead because you eliminate redundant dependencies by using it.
Also note, that when you change the header file, it causes all files that include it to be recompiled.
These questions will also help you:
What are the drawbacks of forward declaration?
What is the purpose of forward declaration?
Don't try to make your compilation efficient. There be dragons. Just include A.hpp in B.hpp.
The standard practice for C and C++ header files is to wrap all of the header file in an #ifndef to make sure it is compiled only once:
#ifndef _A_HPP_
#define _A_HPP_
// all your definitions
#endif
That way, if you #include "A.hpp" in B.hpp, you can have a program that includes both, and it won't break because it won't try to define anything twice.
I've been fighting with my compiler for too long.
Problems with circular includes, redefinitions, "missing ';' before *" and so on.
This seems like the place to get a good answer.
How do I include everything into everything else, and never have to worry about the subtleties of includes ever, ever again?
What combination of #DEFINE, #pragma, #include, or whatever else do I need to do to ensure that data types in the murky depths of my project hierarchy will have no difficulty knowing what anything else is?
This is not a troll post, incase such a concept is entirely unthinkable, nor is it posted in the middle of being angry.
I'm simply curious as to whether or not such a possibility exists. Dealing with spaghetti includes is probably the biggest headache I have to deal with in C++, and getting rid of it would increase my workflow significantly.
Cheers,
Brian
Forward deceleration in the headers and inclusions in the implementation (.c, .cpp, etc).
Good question. I would like to know how to do this, too. Here's some of my tricks:
Figuring the file hirechary structure (which file use which file) to draw a raw concept graph.
Using the following code structure is helpful for prevent RE-DEFINING. Details can be found here.
#ifndef MY_CLASS
#define MY_CLASS
#endif
It means if the file is already included, it will not be included again.
in the beginning of every header file,
#ifndef __MYHEADER_H__
#define __MYHEADER_H__
in the end,
#endif /* __MYHEADER_H__ */
can avoid contain a header file repeatedly.
if you use visual stuido, you can just put
#pragma once
in the beginning of header file.
By the way, you can use some static code check tool to find these kinds of issues, such as lint.
It's a well known issue this damn error
expected class-name before ‘{’ token
Well, despite my hard working and googling, I could not solve this error. Sorry. This is my last shore.
In ui.cpp of a project of mine I do:
#include "wfqueue_proxy_factory.hpp"
OK, this raises this stupid error in my compiler:
In file included from
wfqueue_proxy_factory.hpp:29,from
ui.cpp:28:
wfqueue_manager_proxy.hpp:42: error:
expected class-name before ‘{’ token
There are three classes in my project:
First
// wfqueue_proxy_factory.hpp
#ifndef _WFQUEUE_PROXY_FACTORY_HPP
#define _WFQUEUE_PROXY_FACTORY_HPP
#include "wfqueue_manager_proxy.hpp"
// ...
class WFQueueProxyFactory {
//...
};
#endif
Second
// wfqueue_manager_proxy.hpp
#ifndef _WFQUEUE_MANAGER_PROXY_HPP
#define _WFQUEUE_MANAGER_PROXY_HPP
#include "workflow.hpp"
#include "wfqueue.hpp"
// ...
class WFQueueManagerProxy : public WFQueue { // This is the problem (line 42)
//...
};
#endif
Third
// wfqueue.hpp
#ifndef _WFQUEUE_HPP
#define _WFQUEUE_HPP
#include "workflow.hpp"
class WFQueue {
// ...
};
#endif
PLEASE PLEASE PLEASE note that I use ; after } of every class, I checked out EVERY header in my project looking for this problem and didn't find any class not followed by ; after its closing bracket. This is valid for workflow.hpp which is a simple class (not deriving from any class, just a plain class).
WFQueue is some sort if interface, I use this pattern with other classes too and they work. WFQueue contains some virtual pure methods... problem should not be here anyway.... I suppose this because I use another "interface" class with other classes and they work fine.
This error disappears if I do this:
// wfqueue_manager_proxy.hpp
#ifndef _WFQUEUE_MANAGER_PROXY_HPP
#define _WFQUEUE_MANAGER_PROXY_HPP
#include "workflow.hpp"
#include "wfqueue.hpp"
// ...
class WFQueueManagerProxy {
//...
};
#endif
Don't really know how to solve this problem... please help me.
Thank you
You should run the preprocessor on your code but not compile it, and examine the result. To do this, copy the command which runs the failing compilation, and with most compilers you'd then remove the -o outfile option and add something like -E (see your compiler's documentation for the flag which does preprocessing only).
The compiler will emit (on stdout) the entire translation unit with all #includes and such resolved, so you can clearly see what is missing (just search for the line of code that matches the error line, then look up to see what declarations you find). If it's still not clear what the problem is, write the preprocessed output to a file and try compiling that. You can then tweak the preprocessed source and see what's needed to fix it.
Just a wild guess: Your error says that in
class WFQueueManagerProxy : public WFQueue { // This is the problem (line 42)
//...
};
there must be a class name before {. Therefore I assume that the compiler doesn't know that WFQueue is a class. Are you sure that its definition is included? I mean, maybe in wfqueue.hpp the class is named WfQueue or different in some other way?
The problem might be in misnamed include guards. Try to check if they are really unique per file. It seems that you made it to disable the definition of WFQueue while compiling WFQueueManagerProxy.
It's something it never happened... my god sorry...
It seems that my virtual machine backup disk collided with the original one. I run my project on a virtual machine, making the backup, 2 hours ago, probably messed up something... I adjusted it and now the virtual machine can locate the correct folder and the correct files to compile. It was amazing ahaha and obvious, the ols files g++ tried to compile where a previous version filled with mistakes... This was one of that bugs... a guard header repeated.
Icecrime was right... despite I looked for repetitions in my files, in the previous version, where I didn't fix this problem, there were some files I pasted and forgot to change guard header.
Thank you everyone for your patience and effort.
I'm sorry I didn't notice this very strange virtual disk collision in my machine. Thanks again.
Make sure you typed
using namespace omnetpp;
after includes. It solved my problem.