UPDATE:
Now I have this, and it does not compile:
A.h:
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getfoo();
};
#endif
A.cpp:
#include "A.h"
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
#ifndef B_H
#define B_H
class B {
private:
A myA;
public:
B();
int getAvalue();
};
#endif
B.cpp:
#include "A.h"
#include "B.h"
int B::getAvalue(){
return myA.getfoo();
}
Errors:
b.h line 6: C2146: missing ';' before identifier 'myA'
b.h line 6: C4430: missing type specifier - int assumed
b.h line 6: C4430: missing type specifier - int assumed
END UPDATE
I have written 2 classes in different cpp and header files: class A and class B.
Class B uses class A as a private variable and the default constructor of class A is never called.
Here is my code:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
class B {
public:
int getAvalue();
};
B.cpp:
#include "A.h"
class B {
private:
A myA;
public:
int getAvalue();
};
int B::getAvalue(){
return myA.getfoo();
}
classtest.cpp:
#include "stdafx.h"
#include <iostream>
#include "B.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
B stackB;
cout << stackB.getAvalue() << endl;
B* storeB = new B();
cout << storeB->getAvalue() << endl;
cin.get();
return 0;
}
The output is never 5 and the breakpoint inside the constructor A::A() is never triggered. It doesn't matter if I use B globally or locally. This sample works totally fine if I put the classes and functions in one single file.
If I add an empty default constructor to class B, the default constructor of class A gets called, but then Visual Studio 2008 complains about stack corruption around variable stackB.
What am I doing wrong?
Just with this class alone:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo() {
return foo;
}
You are declaring class A in A.h.
Then in your implementation(cpp) file, you are then again declaring class A.
You are also forgetting to include A.h in A.cpp. If you included the header into the cpp; the compiler would of thrown out errors telling you what was wrong. You are also missing either header guards, or the pragma directive.
Your class should look like this:
A.h
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getFoo() const; // const to return member and prevents modification
};
#endif // !A_H
A.cpp
#include "A.h" // you forgot to include the header
A::A() : // class constructor using it's member initializer list
foo( 5 ) {
}
int A::getFoo() const {
return foo;
}
Now once you fix your class, then working on class B should not be a problem. However there is one thing to be careful of when including a header file of one class into another; you can end up with circular includes. The best way to prevent that is to use a class prototype in the header and include its header in the containing class's cpp file. There are some cases where a class proto type will not work, but I'll leave that up to you to do the research.
How to use Class Prototype in C++
Class B might look like this:
B.h
#ifndef B_H
#define B_H
// #include "A.h" // uncomment this if prototype below doesn't work.
class A; // class prototype may not work in all cases;
// If the above prototype does not work; comment it out
// and replace it with #include "A.h".
class B {
private:
A myA;
public:
B(); // remove default
int getAValue() const;
};
#endif // !B_H
B.cpp
#include "B.h"
#include "A.h" // If class A's prototype in the header does not work
// then comment this out and place it in this class B's header by
// replacing it with the prototype.
B::B() {} // default constructor (should make this complete type)
int B::getAValue() const {
return myA.getFoo();
}
And this should help to fix your problems. If using the class prototype does not work in the header because in some cases it may not; you can remove the prototype declaration from the header and replace it with the include directive of that class and remove its include from the cpp file.
Related
I'm having an issue where it appears an implementation file is recognizing only the forward declaration of another class, and not its actual declaration. I've tried using various guards with imports and taking out the forward declaration but to no avail.
Class A has a function "decode" which takes one argument of type B that's defined in a separate file. I'd like to keep all .h's and .cpp's as distinct files. Here they are.
A.h:
class B;
class A{
private:
string sentence;
public:
A();
void decode(const B& decoder);
};
B.h:
class B{
private:
int code[26];
public:
B();
int getCode(int index);
};
A.cpp:
#include "A.h"
A::A(){}
double A::decode(const B& decoder){
B.getCode(1);
//other things
}
B.cpp:
#include "B.h"
B::B(){}
int B::getCode(int index){};
and the driver:
#include "B.h"
#include "A.h"
using namespace std;
int main(int argc, char* argv[]){
B myB;
A myA;
myA.decode(B);
}
I'm compiling this with g++ -Wall driver.cpp B.cpp A.cpp, but get hit with an error that looks like:
A.cpp:4 error: invalid use of incomplete type 'const class B'
I've looked through a ton of similar threads trying to find the answer, but nothing has worked for me yet. Any ideas?
Since you are using B's member function getCode in your A.cpp file, the forward declaration only will not suffice as it says nothing about B's member functions. The entire B declaration needs to be available. To do that, include the "B.h" header in your A.cpp file:
#include "B.h"
As pointed out in the comments you should also utilize the header guards for A.h and B.h headers.
Best practice is that every .h file includes everything it needs. That means A.h shall include B.h.
A.h:
#pragma once // Or equivalent include-guard macros
#include "B.h"
class A{
private:
string sentence;
public:
A();
void decode(const B& decoder);
};
B.h:
#ifndef B_h
#define B_h true
class B{
private:
int code[26];
public:
B();
int getCode(int index);
};
#endif
A.cpp:
#include "A.h"
A::A(){}
double A::decode(const B& decoder){
B.getCode(1);
//other things
}
B.cpp:
#include "B.h"
B::B(){}
int B::getCode(int index){};
and the driver:
#include "A.h"
void main(){
B myB;
A myA;
myA.decode(B);
}
Can you figure out how to solve this circular inclusion problem?
C extends B and B includes A. A includes C. Every forward declaration I tried hasn't worked.
Errors
Error 1 error C2504: 'B' : base class undefined
Error 2 error C3668: 'C::c' : method with override specifier 'override' did not override any base class methods
File A.h:
#pragma once
#include "C.h"
struct A
{
A();
C c;
};
File B.h:
#pragma once
#include "A.h"
struct A;
struct B
{
virtual void c() = 0;
A* a;
};
File C.h:
#pragma once
#include "B.h"
struct B;
struct C : public B
{
void c() override;
};
The solution is always the same and it looks like you were on the right track. However, you're not using forward declartions correctly. There should be many examples of how to do this for example here.
B.h
// Why are including "A.h" here, this is causing your circular include
// issue, it needs to be moved to your implementation (e.g., "B.cpp")
#include "A.h"
struct A; // Forward declaration, good
struct B
{
virtual void c() = 0;
A* a; // A pointer only requires the above forward declartion
};
C.h
#include "B.h" // Necessary since you're extending `B`
struct B; // This forward declaration is superfluous and should be removed
struct C : public B
{
void c() override;
};
I'm having a problem compiling with circular dependencies. I did some research, and people recommended using a forward declaration. I'm still having a problem with that because the class that has a forward declaration is using methods from the forwarded class. This causes the compiler to give me the error "Class A has incomplete field b". How can I get around the circular dependency where A requires B, and B requires A?
A.h:
#ifndef A_H_
#define A_H_
#include <iostream>
//#include "B.h"
class A
{
class B;
private:
B b;
public:
A();
~A();
void method();
};
#endif
A.cpp:
#include <iostream>
#include "A.h"
A::A()
{
}
A::~A()
{
}
void A::method()
{
b.method();
}
B.h:
#ifndef B_H_
#define B_H_
#include <iostream>
//#include "A.h"
class B
{
class A;
private:
A a;
public:
B();
~B();
void method();
};
#endif
B.cpp:
#include <iostream>
#include "B.h"
B::B()
{
}
B::~B()
{
}
void B::method()
{
a.method();
}
Your classes cannot work. Every A contains a B, which contains an A, which contains a B, etc., ad infinitum.
This will not work as you have constructed it as A requires full knowledge of the size of B and B requires the same of A, which is only given by seeing the full declaration.
The following is not valid:
class B;
class A {
B b;
};
Why? How much space do we allocate for an instance of A? sizeof(A) = sizeof(B) = undefined There is a workaround, however:
class B;
class A {
B* b_ptr;
B& b_ref;
};
This is perfectly valid, since the pointer and reference's size are known, regardless of the type they point to.
In at least one case (either A or B) you have to remove the dependence on the complete type. For example, below I've removed the need for A to have the complete type of B within the A.h header file:
// A.h
class B;
// B used as a reference only, so the complete type
// is not needed at this time
class A
{
public:
A(B& b) : b_(b) {}
void method();
private:
B& b_;
};
// A.cpp
// B is used, and the complete type is required
#include "B.h"
void A::f()
{
b.method();
}
You could try to replace one of the member by a pointer to the other class :
class B;
class A
{
private:
B* b;
public:
A();
~A();
void method();
};
My code looks something like this:
main.cpp
#include <iostream>
#include "A.h"
#include "B.h"
using namespace std;
int main(){
int d,f;
A c();
d = c.GetStuff();
B *d = new C();
f = d->Get();
return 0;
}
A.h
#ifndef A_H
#define A_H
class A
{
int a;
public A();
int GetStuff() {return(a) ;}
};
#endif
A.cpp
#include "A.h"
A::A()
{
a = 42;//just some value for sake of illustration
}
B.h
#ifndef B_H
#define B_H
Class B
{
public:
virtual int Get(void) =0;
};
class C: public B {
public:
C();
int Get(void) {return(a);}
};
#endif
B.cpp
#include "B.h"
C::C() {
a // want to access this int a that occurs in A.cpp
}
My question is, what is the best way to gain access to "a" in B.cpp?
I tried using class "friend", but I am not getting results.
Any suggestions?
Thanks!
Two different answers, depending on what you mean
If each A object is meant to have it's own unique 'a' variable (which is how you've defined it) then you'll need to pass an A into the constructor of C:
C::C(const A &anA) {
int foo= anA.a; //
}
And, invoking the constructor becomes:
A myA;
B *myC = new C(myA); // You picked confusing names for your classes and objects
However, if you intended all A objects to share a common a value, then you should declare a and getStuff as static in A :
class A
{
static int a;
public:
static int GetStuff() {return a;};
... and access it as A::GetStuff() in the C constructor.
I have two classes, class A and class B.
A.h -> A.cpp
B.h -> B.cpp
And then, I set B as a member in class A. Then, class A can access class B by
#include <B.h>
But, how can I get the pointer of class A in class B and access the public member of class A?
I found some information about on the internet: a Cross-class. They said you can make it by setting the class B as a nested class in class A.
Do you have any other advice?
sorry.
myCode: as follow..
class A:
#ifndef A
#define A
#include "B.h"
class A
{
public:
A() {
b = new B(this);
}
private:
B* b;
};
#endif
#ifndef B
#define B
#include"A.h"
class B
{
public:
B(A* parent = 0) {
this->parent = parent;
}
private:
A* parent;
};
#endif
Just use forward declaration. Like:
A.h:
#ifndef A_h
#define A_h
class B; // B forward-declaration
class A // A definition
{
public:
B * pb; // legal, we don't need B's definition to declare a pointer to B
B b; // illegal! B is an incomplete type here
void method();
};
#endif
B.h:
#ifndef B_h
#define B_h
#include "A.h" // including definition of A
class B // definition of B
{
public:
A * pa; // legal, pointer is always a pointer
A a; // legal too, since we've included A's *definition* already
void method();
};
#endif
A.cpp
#inlude "A.h"
#incude "B.h"
A::method()
{
pb->method(); // we've included the definition of B already,
// and now we can access its members via the pointer.
}
B.cpp
#inlude "A.h"
#incude "B.h"
B::method()
{
pa->method(); // we've included the definition of A already
a.method(); // ...or like this, if we want B to own an instance of A,
// rather than just refer to it by a pointer.
}
Knowing that B is a class is enough for compiler to define pointer to B, whatever B is. Of course, both .cpp files should include A.h and B.h to be able to access class members.