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.
Related
I want to show result is 2. (Now result is 1.)
How should I do? (I want to call B::test(). But Actually code cannot access b.h, b.c in main.c)
also I want to know that error from "public: virtual int test() {return 1;}" to "protected: virtual int test() {return 1;}" in a.h
the inheritance relationship are
super class A sub class B
super class A sub class C
but I can access A class in main.c
I want to result 2. ("a.test()" could not call "b.test()")
// a.h
#ifndef _A_
#define _A_
class A {
public:
A() {};
~A() {};
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
#endif
// b.h
#ifndef _B_
#define _B_
#include "a.h"
class B : public A {
public:
B() {};
~B() {};
private:
int test() override;
friend class A;
};
#endif
// b.c
#include "b.h"
int B::test()
{
return 2;
}
// c.h
#ifndef _C_
#define _C_
#include "a.h"
class C : public A {
public:
C() {};
~C() {};
private:
int test() override;
friend class A;
};
#endif
// c.c
#include "c.h"
int C::test()
{
return 3;
}
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
Consider your code:
// main.c
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = new A();
cout << a->test() << "\n";
return 0;
}
The key decider on behaviour is =new A().
If you change this to =new B() then you would get the result of '2' that you want.
However, you've had added the restriction 'code cannot access b.h'. This means that =new B() will not compile. Where does this restriction come from? You could achieve this with an extremely complicated factory pattern, but it seems unlikely this is what you are trying to do.
Access specifiers (private, protect, public) should be the same for the same method (test() in this case) at every level in the hierarchy. This is not absolutely enforced by the compiler, but is a clear best practice. There's very little difference her between making test() private or protected, but in both cases the expression:
a->test()
will fail in main, because it is outside of the class, and can only access public members.
Also worth pointing out that your friend declarations are entirely unnecessary in the code as shown.
Create object of type B, you still will be able to call test method, because A::test is public. This code will print 2:
int main(void)
{
A *a = new B();
// ^
cout << a->test() << "\n";
delete a; // (1)
return 0;
}
Also line (1) won't work properly unless you make A's destructor virtual (When to use virtual destructors?):
class A {
public:
A() {};
virtual ~A() {};
// ^^^^^^^
//protected:
virtual int test() {return 1;}
private:
friend class B;
};
UPD If for some reason you can't include b.h you can do the following:
a.h:
#ifndef _A_
#define _A_
class A {
...
};
A* CreateB();
#endif
a.c:
#include "a.h"
#include "b.h"
...
A* CreateB() {
return new B();
}
main.c:
#include <iostream>
#include "a.h"
using namespace std;
int main(void)
{
A *a = CreateB();
cout << a->test() << "\n";
delete a;
return 0;
}
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.
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();
};
Here is what I am trying to do, I want the class A's constructor to call B's constructor for an object of B, like this main()->A->B
A.cpp:(included B.h)
A::A(){
B foo;
}
B.h:
class B{
B(){//some code};
};
but GCC won't compile and says A::B foo has initializer but incomplete type. I am guessing the compiler saw no local class of B defined in A, so it complained and didn't know the Class B was from another file. My question is how to construct an B's object in A's constructor like above.I am sure I am missing some fundamentals about C++, please bear with me. Thank you in advance.
Try
class A
{
public:
A(); // Don't define A::A() here
// As the compiler has not seen B
};
class B
{
public:
B() {}
};
// At this point both classes have been seen
A::A()
{
::B foo; // So now you can use B
// Note I am using ::B here
// As the error message suggests that you have some class B defined
// Within A which is confusing it. the prefix :: means take the class
// B from the global scope rather than a closer scope.
}
You do not have any class of type A::B. From your comment, it looks like you are trying to use a pointer to B by calling it A::B *. This is incorrect. A pointer to B is always B *, regardless of where it appears. From what you said, it looks like you want something like this:
a.hpp
#ifndef A_HPP_
#define A_HPP_
class B;
class A {
public:
A(B * b);
private:
B * my_very_own_b;
};
#endif // A_HPP_
a.cpp
#include "a.hpp"
#include "b.hpp"
A::A(B * b):
my_very_own_b(b)
{
}
b.hpp
#ifndef B_HPP_
#define B_HPP_
class B {
public:
B();
private:
int x;
};
#endif // B_HPP_
b.cpp
#include "b.hpp"
B::B():
x(0)
{
}
main.cpp
#include "a.hpp"
#include "b.hpp"
int main() {
B b;
A a(&b);
return 0;
}
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.