batuman
batuman

Reputation: 7304

Data access from a member function of different classes in C++

I am confused how to implement data member access from a different class. I have three classes in three different header files.

A.h
#include "B.h"
#include "C.h"
class A{

    B *b;
    friend void dataaccess_b_from_class_A(int a);
}

B.h
class B{

}

C.h
class C{

   void dataaccess_b_from_class_A(int a);
}
void C::dataaccess_b_from_class_A(int a)
{
   b = new B(); //I got error as symbol b could not be resolved.
}

I like dataaccess_b_from_class_A() method from class C access data B *b from Class A. I put friend function inside class A, but I got error as symbol b could not be resolved.How can I implement it?

EDIT1: According to the discussion 'gmas80', what I did was

class B; // forward declaration

class A{
public:
    A(){};
private:
    static B* b; // since in the dataaccess_to_class_A you are using new
    friend class C; // this make b and dataaccess_from_class_C accessible
};

class B{
public:
    B(){ cout << "B" << endl; };
   // add content
};

class C{
public: // you need this keyword if you want to call this function from outside
   void dataaccess_to_class_A(A a);
};

void C::dataaccess_to_class_A(A a)
{
   A::b = new B(); //Error as undefined reference to class A::b

   cout << "C" << endl; // test if called
}

If I don't include static, I got b could not be resolved. If I include static, I got undefined reference. Thanks

Upvotes: 0

Views: 64

Answers (2)

gmas80
gmas80

Reputation: 1268

You have included so many mistakes in a so small piece of code! why don't you start simpler? Here a modified single-file version of your code that compiles:

#include <iostream>
using namespace std;

class B; // forward declaration

class A{
public:
    A(){};
private:
    B* b; // since in the dataaccess_to_class_A you are using new
    void dataaccess_from_class_C(){ cout << "A" << endl; }; // test if called
    friend class C; // this make b and dataaccess_from_class_C accessible
};

class B{
public:
    B(){ cout << "B" << endl; };
   // add content
};

class C{
public: // you need this keyword if you want to call this function from outside
   void dataaccess_to_class_A(A a);
};

void C::dataaccess_to_class_A(A a)
{
   a.b = new B(); // this is a potentially memory leak if you will not delete in somehow
   a.dataaccess_from_class_C();
   cout << "C" << endl; // test if called
}

// it is better if you post runnable code
int main() {
    C c;
    A a;
    c.dataaccess_to_class_A(a);
}

AFTER EDIT1

Now you can start to move the class in a header file, but you need to add guardians to avoid multiple definitions..

a.h

#ifndef H_GUARDIAN_A
#define H_GUARDIAN_A

#include <iostream>
using namespace std;

class B; // forward declaration

class A
{
public:
    A()
    {};
private:
    B* b; // since in the dataaccess_to_class_A you are using new
    void dataaccess_from_class_C()
    {
        cout << "A" << endl;
    }; // test if called
    friend class C; // this make b and dataaccess_from_class_C accessible
};

class B
{
public:
    B()
    {
        cout << "B" << endl;
    };
    // add content
};

class C
{
public: // you need this keyword if you want to call this function from outside
    void dataaccess_to_class_A( A a );
};

void C::dataaccess_to_class_A( A a )
{
    a.b = new B(); // this is a potentially memory leak if you will not delete in somehow
    a.dataaccess_from_class_C();
    cout << "C" << endl; // test if called
}

#endif

main.cpp

#include "a.h"

// it is better if you post runnable code
int main()
{
    C c;
    A a;
    c.dataaccess_to_class_A( a );
}

Does it make sense for you? I simple moved the class declarations in another file that is included..

EDIT2

Now we split the class definitions in three different headers..

a.h

#ifndef H_GUARDIAN_A
#define H_GUARDIAN_A

#include <iostream>
using namespace std;

class B;

class A
{
public:
    A(): b(NULL){}; // initialize to NULL the b pointer
    ~A(); // new entry: destructor to eventually delete b (only member function declaration)
private:
    B* b; // since in the dataaccess_to_class_A you are using new
    void dataaccess_from_class_C()
    {
        cout << "A" << endl; // test if called
    }; 
    friend class C; // this make b and dataaccess_from_class_C accessible
};

#endif

a.cpp // new entry! it avoids circular dependency.. the destructor is defined here

#include "a.h"
#include "b.h"

A::~A() // destructor that eventually clean memory for b
{
    if( b ) delete b;
}

b.h

#ifndef H_GUARDIAN_B
#define H_GUARDIAN_B

#include "a.h"

class B
{
public:
    B()
    {
        cout << "B" << endl;
    };
    // add content
};

#endif

c.h

#ifndef H_GUARDIAN_C
#define H_GUARDIAN_C

#include "b.h"

class C
{
public: // you need this keyword if you want to call this function from outside

    void dataaccess_to_class_A( A a );
};

void C::dataaccess_to_class_A( A a )
{
    a.b = new B(); // this is a potentially memory leak if you will not delete in somehow
    a.dataaccess_from_class_C();
    cout << "C" << endl; // test if called
}

#endif

main.cpp

#include "c.h"

// it is better if you post runnable code
int main()
{
    C c;
    A a;
    c.dataaccess_to_class_A( a );
}

Upvotes: 1

mzu
mzu

Reputation: 723

add

include "B.h"

in the beginning if the C.h and define the type of b

B b( new B() );

also, specify the fully qualified method in your freind declaration:

friend void C::dataaccess_b_from_class_A(int a);

include C.h into A.h, and do not forget include guards in each header

Another point. Why are you defining C::dataaccess_b_from_class_A in the header? I would suggest to do it in a separate file. Say, "C.cpp".

Upvotes: 0

Related Questions