When I build and run this code in Eclipse CDT, I expect it to print 1. It prints -1992206527 instead. Why is this?
Here's my code.
A.h
#ifndef A_H
#define A_H
class A {
private:
int a;
public:
A();
~A();
void printNum();
};
#endif
A.cpp
#include <iostream>
#include "A.h"
A::A() :
a(1)
{
}
A::~A(){}
void A::printNum(){
std::cout << a << std::endl;
}
B.h
#ifndef B_H_
#define B_H_
class A;
class B {
private:
A* obj;
public:
B();
~B();
int run();
};
#endif
B.cpp
#include "A.h"
#include "B.h"
B::B() {}
B::~B() {}
int B::run(){
obj->printNum();
return 0;
}
main.cpp
#include "B.h"
int main(int argc, char **argv) {
B b;
return b.run();
}
To make it print 1, you must initialize B::obj. Below is a B.cpp with obj being properly initialized/ deallocated.
#include "A.h"
#include "B.h"
B::B() : obj(new A) {}
B::~B() { delete obj;}
int B::run(){
obj->printNum();
return 0;
}
Alternatively, you could make obj be an object type A(i.e declare obj as A obj;), instead of making it a pointer to an object of type A. This would necessitate including A.hin B.h.
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 have two class hierarchies: As and Bs. As have a virtual method return Bs, and Bs have a virtual method return As.
A.h
#pragma once
class B;
struct A
{
virtual B* f() = 0;
};
A1.h
#pragma once
#include "A.h"
#include "B1.h"
struct A1 : public A
{
B1* f() override;
};
B.h
#pragma once
class A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
#include "A1.h"
struct B1 : public B
{
A1* g() override;
};
It doesn't compile with errors in VS2015
overriding virtual function return type differs and is not covariant from A
With class forward declaration
class A1 : public A;
it should work. But C++ doesn't support such class forward declaration. How to fix it?
When dealing with circular references, use forward declarations instead of #include statements where appropriate.
Also, the header files themselves should have guards in them to avoid declaring their content multiple times when #include'd multiple times. The guards themselves can use either an #ifndef/#define pair, or a #pragma once, depending on your compiler.
A.h
#ifndef A_H
#define A_H
struct B;
struct A
{
virtual B* f() = 0;
};
#endif
Or:
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#ifndef A1_H
#define A1_H
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
#endif
Or:
#pragma once
#include "A.h"
struct B1;
struct A1 : public A
{
B1* f() override;
};
A2.h
#ifndef A2_H
#define A2_H
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
#endif
Or:
#pragma once
#include "A.h"
struct B2;
struct A2 : public A
{
B2* f() override;
};
B.h
#ifndef B_H
#define B_H
struct A;
struct B
{
virtual A* g() = 0;
};
#endif
Or:
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#ifndef B1_H
#define B1_H
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
#endif
Or:
#pragma once
#include "B.h"
struct A1;
struct B1 : public B
{
A1* g() override;
};
B2.h
#ifndef B2_H
#define B2_H
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
#endif
Or
#pragma once
#include "B.h"
struct A2;
struct B2
{
A2* g() override;
};
The #include statements to satisfy the forward-declared classes should be used in the method implementation source files, not in their declaring header files:
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B1* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B2* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A1* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A2* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
That being said, forward declaring the structs is the only way to deal with circular references. But since you can't forward declare hierarchies, I don't think there is a solution to your problem without rethinking your design. If that is not an option, you will have to stay way from using covariant return values.
A.h
#pragma once
struct B;
struct A
{
virtual B* f() = 0;
};
A1.h:
#pragma once
#include "A.h"
struct A1 : public A
{
B* f() override;
};
A2.h
#pragma once
#include "A.h"
struct A2 : public A
{
B* f() override;
};
B.h
#pragma once
struct A;
struct B
{
virtual A* g() = 0;
};
B1.h
#pragma once
#include "B.h"
struct B1 : public B
{
A* g() override;
};
B2.h
#pragma once
#include "B.h"
struct B2
{
A* g() override;
};
A1.cpp:
#include "A1.h"
#include "B1.h" // <--
B* A1::f()
{
return new B1; // or wherever the B1 object comes from...
}
A2.h
#include "A2.h"
#include "B2.h" // <--
B* A2::f()
{
return new B2; // or wherever the B2 object comes from...
}
B1.cpp
#include "B1.h"
#include "A1.h" // <--
A* B1::g()
{
return new A1; // or wherever the A1 object comes from...
}
B2.cpp
#include "B2.h"
#include "A2.h" // <--
A* B2::g()
{
return new A2; // or wherever the A2 object comes from...
}
It just means you will have to use type-casts wherever you were relying on covariance when calling f() and g().
A.h
#ifndef A_H
#define A_H
#include "B.h"
class A{
public:
B* b;
A(){
b->ownership = this;
};
};
#endif
B.h
#ifndef B_H
#define B_H
class A;
class B{
public:
A* ownership;
};
#endif //B_H
main.cpp
#include "A.h"
class C{
A a1;
A a2;
};
int main()
{
C c;
return 0;
}
Commands:
g++ -g main.cpp -o main
./main
This program fails with segmentation fault.
"gdb main core" told me that error was in string: "b->ownership = this;"
Question: Where is my fault? What I should know not to make more of these errors? Thank you.
The problem is in this class:
class A
{
public:
B* b;
A()
{
b->ownership = this;
}
};
You're dereferencing b but you haven't created an instance of B.
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.