I am getting those 2 errors :
-error: expected identifier before numeric constant
-error: expected ',' or '...' before numeric constant
I try from the second class to have an object to first class with parameters and it gives me those 2 errors. Without parameters works fine.
This is main:
#include<iostream>
#include "c1.h"
#include "c1.cpp"
#include "c2.h"
#include "c2.cpp"
using namespace std;
int main()
{
c2 obj2();
return 0;
}
This is first class header:
#ifndef C1_H
#define C1_H
class c1
{
public:
c1(int,int);
};
#endif // C1_H
And its cpp file:
#include "c1.h"
c1::c1(int x,int y)
{
std::cout << "\nCtor c1\n" << x << "\n" << y << "\n";
}
And the second file header:
#include "c1.h"
#ifndef C2_H
#define C2_H
class c2
{
public:
c2();
c1 obj1(10,2);
};
#endif // C2_H
And its cpp:
#include "c2.h"
c2::c2()
{
std::cout << "\nCtor c2\n";
}
Thank's.
Don't use CPP files in includes.
For solution to this problem, you can change the object to pointer and use something like c1* obj1=new c1(10,2) and it should work.
A better way of doing this is, add a class member c1* obj1; and use constructor of c2 to really create the c1 object obj1=new c1();
Related
I have these files structure:
main.cpp
#include "main.h"
Map map;
Fruit fruit;
Stone stone;
main.h
extern Map map;
extern Fruit fruit;
extern Stone stone;
map.h
#include "main.h"
class Map {public: int size = 20;};
fruit.h
#include "main.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
stone.h
#include "main.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
The problem is when I'm trying to use map.size and fruit.pos I get error:
'map': undeclared identifier
The same with stone. So, what's wrong?
main.h should include map.h not the other way around.
main.h should include fruit.h not the other way around.
main.h should include stone.h not the other way around.
Also you should add include guards to your header files.
EDIT
Here's one way that works, (I can't believe I recommending code like this but still)
// map.h
#ifndef MAP_H
#define MAP_H
class Map {public: int size = 20};
extern Map map;
#endif
// fruit.h
#ifndef FRUIT_H
#define FRUIT_H
#include "map.h"
class Fruit { public: int pos = 1; draw() {return map.size;} };
extern Fruit fruit;
#endif
// stone.h
#ifndef STONE_H
#define STONE_H
#include "map.h"
#include "fruit.h"
class Stone { public: draw() {return map.size * fruit.pos;} };
extern Stone stone;
#endif
// main.cpp
#include "map.h"
#include "fruit.h"
#include "stone.h"
Map map;
Fruit fruit;
Stone stone;
This is not how you are supposed to write code.
Files (*.h or *.cpp) should only include files that they directly depend upon.
Files should not include files that they do not depend upon.
One way to break cyclical dependencies is to put the implementation in the foo.cpp source file instead of inline in the foo.h header file.
One way to break dependencies on global variables is to instead pass them in as parameters instead of having them hard-coded into the routines.
Use of a forward declaration can be used to avoid including an header file that is only used to declare the type. Only when the details of the type, such as its methods and footprint, are not important. Alas, forward declarations for template classes are trickier.
For the files in the OP example, here's an alternative implementation incorporating those suggestions.
fruit.h
#ifndef FRUIT_H
#define FRUIT_H
class Map;
class Fruit {
public:
int pos = 1;
auto draw(Map const&) -> int;
};
#endif
map.h
#ifndef MAP_H
#define MAP_H
class Map {
public:
int size = 20;
};
#endif
stone.h
#ifndef STONE_H
#define STONE_H
class Fruit;
class Map;
class Stone {
public:
auto draw(Map const& map, Fruit const& fruit) -> int;
};
#endif
fruit.cpp
// Identity.
#include "fruit.h"
// Other dependencies.
#include "map.h"
auto Fruit::draw(Map const& map) -> int {
return map.size;
}
stone.cpp
// Identity.
#include "stone.h"
// Other dependencies.
#include "fruit.h"
#include "map.h"
auto Stone::draw(Map const& map, Fruit const& fruit) -> int {
return map.size * fruit.pos;
}
main.cpp
#include <iostream>
#include "fruit.h"
#include "map.h"
#include "stone.h"
using std::cout;
int main() {
auto map = Map{};
auto fruit = Fruit{};
auto stone = Stone{};
map.size = 17;
fruit.pos = 3;
cout << "map.size is " << map.size << "\n";
cout << "fruit.pos is " << fruit.pos << "\n";
cout << "fruit.draw(map) is " << fruit.draw(map) << "\n";
cout << "stone.draw(map, fruit) is " << stone.draw(map, fruit) << "\n";
}
I'm trying to declare a class object as extern but am getting the below error:
g++ a1.cpp -std=c++11
In file included from b1.h:5:0,
from a1.cpp:2:
c1.h:6:8: error: ‘b1’ does not name a type
extern b1 obj_b1;
^
I have looked in
Issue declaring extern class object
and
'[Class name]' does not name a type in C++
and I THINK I am following the steps mentioned there. But couldn't find what's the issue.
Files are :
a1.cpp
#include<iostream>
#include "b1.h"
b1 obj_b1;
int main(){
//access object from class B
std::cout << " test " << std::endl;
std::cout << " obj_b1 value is " << obj_b1.value << std::endl;
obj_b1.value = 6;
return 0;
}
b1.h
#ifndef CLASS_B1
#define CLASS_B1
#include "c1.h"
class b1{
public:
int value=5;
int print_value();
};
#endif
b1.cpp
#include <iostream>
#include "b1.h"
int b1::print_value(){
std::cout << "value in b1 is " << value << std::endl;
}
c1.h
#ifndef CLASS_C1
#define CLASS_C1
#include "b1.h" // this is an attempt to fix issue, but didnt work
extern b1 obj_b1; // Is there a better place to declare this ?
class c1 {
private:
int c1_value=10;
int c1_print_value();
};
#endif
c1.cpp
#include<iostream>
#include "c1.h"
int c1::c1_print_value()
{
std::cout << "in c1 , value is " << c1_value << std::endl;
std::cout << " obj_b1.value is " << obj_b1.value << std::endl;
return 0;
}
I can not understand why the compiler complains about b1, when I have added b1.h just above the extern declaration. Can someone help to solve the issue ?
b1.h includes c1.h, and c1.h includes b1.h. This is is a mess. By using the #indef/#define combo, you have prevented an infinite recursion, but it is still a mess.
obj_b1 doesn't have anything to do with class c1, so remove extern b1 obj_b1; from c1.h.
Now c1.h doesn't depend on anything in b1.h, so you can remove #include "b1.h" from c1.h.
An for similar reason, you should remove #include "c2.h" from b1.h.
On the other hand c2.cpp does depend on obj_b1 (assuming obj1.name is a typo, and should be obj_b1.name), so you should put extern b1 obj_b1; in b1.h and #include "b1.h" in c2.cpp.
For some extra cleanup, move b1 obj_b1; from a1.cpp to b1.cpp
How can I define an integer in a header file so that each cpp file which includes the header will have static const int id=0 while giving the ability to cpps to redefine it with other value.
I tried to used weak symbol but couldn't make it work.
If you are ok with preprocessor definitions you could do this:
// header.h
#ifndef CLASSID
#define CLASSID 0
#endif
static int id=CLASSID;
// class.cpp
#define CLASSID 1
#include "header.h"
This way a source file may override the default, but may also omit it, which is the sort of weak approach you mentioned.
Here's another solution that uses static variables:
// log.h
#ifndef LOG_H
#define LOG_H
#include <iostream>
#define SETLOGID(v) static logidsetter _logidsetter(_logid, v);
#define LOG(v) std::cout << "id: " << _logid << ": " << (v) << std::endl;
class logidsetter
{
public:
logidsetter(int &id, int val)
{
id = val;
}
};
static int _logid = 0;
#endif
// myclass.h
class myclass
{
public:
myclass();
void run(void);
};
// myclass.cpp
#include "log.h"
#include "myclass.h"
SETLOGID(42)
myclass::myclass()
{
LOG("myclass::cons");
}
void myclass::run(void)
{
LOG("myclass::run");
}
// main.cpp
#include "myclass.h"
#include "log.h"
SETLOGID(1)
int main()
{
myclass mc;
LOG("here's main");
mc.run();
}
The log header defines the static int _logid and provides the macro SETLOGID and the class idsetter. The cpp file may use SETLOGID to redefine the static value. This is done with an instantiation of the class idsetter along with the address of _logid and the desired value. The trick allows to bypass C++'s One Definition Rule.
The output looks like:
id: 42: myclass::cons
id: 1: here's main
id: 42: myclass::run
As you can see, the title is a little nonsense, it's because I really don't know how to call that, but know that I tried hard to find a better title.
I hope you understand what I'm trying to say seeing the rest of the question.
Let's suppose that I have 3 classes, "A", "B", and "C".
The class "A" includes "B" and "C".
The class "B" includes "A"
The class "C" includes "A"
Let's go the code...
#include <iostream>
#include <b.hpp>
#include <c.hpp>
class A
{
public:
A()
{
std::cout << "Hello from A" << std::endl;
A a;
B b;
}
};
#include <iostream>
#include <a.hpp>
class B
{
public:
B()
{
std::cout << "Hello from B" << std::endl;
}
};
#include <iostream>
#include <a.hpp>
class C
{
public:
C()
{
std::cout << "Hello from C" << std::endl;
}
};
This way, everything works fine, the output:
Hello from A
Hello from B
Hello from C
BUT, if I do that:
#include <iostream>
#include <a.hpp>
#include <vector>
class B
{
public:
B()
{
std::cout << "Hello from B" << std::endl;
}
private:
std::vector<A> garage;
};
I got a cascade of errors, including this one (actually, the main one, because of that one, there are others):
error: 'A' was not declared in this scope
std::vector garage;
This is exactly what I want, do you have an idea what I can do? Thank you.
#edit - As answer to #Kerrek SB
I tried to create separated files to each one, header and sources. (.hpp and .cpp) and the error persist.
A.hpp
#ifndef A_HPP
#define A_HPP
#include <iostream>
#include <B.hpp>
#include <C.hpp>
class A
{
public:
A();
};
#endif
A.cpp
#include <A.hpp>
A::A()
{
std::cout << "Hello from A" << std::endl;
B b;
C c;
}
B.hpp
#ifndef B_HPP
#define B_HPP
#include <iostream>
#include <A.hpp>
#include <vector>
class B
{
public:
B();
private:
std::vector<A> garage;
};
#endif
B.cpp
#include <B.hpp>
B::B()
{
std::cout << "Hello from B" << std::endl;
}
C.hpp
#ifndef C_HPP
#define C_HPP
#include <iostream>
#include <A.hpp>
class C
{
public:
C();
};
#endif
C.cpp
#include <C.hpp>
C::C()
{
std::cout << "Hello from C" << std::endl;
}
main.cpp
#include <iostream>
#include <A.hpp>
int main(int argc, char ** argv)
{
A a;
return 0;
}
gcc
g++ -O2 -std=c++11 -I"." -o exchange A.cpp B.cpp C.cpp main.cpp
output
In file included from ./A.hpp:5:0,
from ./C.hpp:5,
from C.cpp:1:
./B.hpp:13:17: error: 'A' was not declared in this scope
std::vector<A> garage;
Separate the class definitions from the class member definitions:
#include <iostream>
#include <vector>
class A { public: A(); };
class B { public: B(); private: std::vector<A> garage; };
class C { public: C(); };
A::A()
{
std::cout << "Hello from A" << std::endl;
// A a; // no, because that's idiotic
B b;
}
B::B()
{
std::cout << "Hello from B" << std::endl;
}
C::C()
{
std::cout << "Hello from C" << std::endl;
}
In a larger project, you would probably have separate header and source files for each of those.
This is really puzzling me. For some reason I get a
"c1 not declared in this scope"
error from the compiler. I am usig Mingw with Code::Blocks. I would assume global variables are global to the program? Am I wrong? TYIA -Roland
// main.h
#include <iostream>
#include "classone.cpp"
#include "classtwo.cpp"
extern AnotherClass c2;
extern TheClass c1;
----------
// main.cpp
#include "main.h"
AnotherClass c2;
TheClass c1;
int main()
{
c1.function5();
c2.function2();
return 0;
}
----------
//classone.h
#include "main.h"
class AnotherClass {
`
public:
void function2();
void function3();
private:
int varone;
int vartwo;
};
----------
// classone.cpp
#include "classone.h"
void AnotherClass::function2() {
std::cout << "Function 2 Check\n";
}
void AnotherClass::function3() {
std::cout << "Function 3 Check";
}
----------
// classtwo.h
#include "main.h"
class TheClass {
public:
void function4();
void function5();
};
----------
// classtwo.cpp
#include "classtwo.h"
void TheClass::function4() {
c1.function2();
std::cout << "Function 2 Check\n";
}
void TheClass::function5() {
std::cout << "Function 3 Check";
}
It's quite silly to include .cpp files like that - only include headers.
Anyway, change main.h to this:
#include <iostream>
extern AnotherClass c2;
extern TheClass c1;
Add this to main.cpp:
AnotherClass c2;
TheClass c1;
Then include main.h in each file which needs it, like this:
// classtwo.cpp
#include "classtwo.h"
#include "main.h"
void TheClass::function4() {
c1.function2();
std::cout << "Function 2 Check\n";
}
void TheClass::function5() {
std::cout << "Function 3 Check";
}
Also, you need include guards if you don't have those already.
You need to include the class declarations in your .cpp files if you want to compile all the code in a single file. Inside classtwo.cpp insert #include "classtwo.h" and do the same for classone at the top of both files.
Standard practice is to separate the class code from the client code, so you should compile the classes into a library and link it to the main program.
Your main .h needs to include the .h files of the 2 classes, for it to work. You do not (and should not ) need to include the .cpp files.