开发者

C++ pointers to class instances

I have an (for C++ programmers better than me) simple problem with classes and pointers. I thought about posting example code describing my problem but I found it easier to just explain it in words.

Assumi开发者_运维问答ng I have three classes:

  • Class A: The main class - it contains an instance of both B and C.
  • Class B: This class contains a method that outputs some string, call it Greet().
  • Class C: This one has a method too, but that method has to call Greet() in the instance of B that is located in class A. Let's name it DoSomethingWithB()

So the program starts, in the main function I create an instance of A. A, again, creates instances of B and C. Then, A calls C.DoSomethingWithB();.

And there my problem begins: I can't access B from inside C.

Obviously, I will need to pass a pointer to B to the DoSomethingWithB() function so that I can call B.Greet() from inside C

Long explanation, short question: How do I do this?

Example code incoming:

#include <iostream>
using namespace std;

class B
{
public:
    void Greet( )
    {
        cout<<"Hello Pointer!"<<endl;
    }
};

class C
{
public:
    void DoSomethingWithB( )
    {
        // ... b.Greet( ); Won't work obviously
    }
};

class A
{
public:
 B b; // Not caring about visibility or bad class/variable names here
 C c;
 void StartTest( )
 {
      c.DoSomethingWithB( );
 }
};

int main( )
{
    A mainInstance;
    mainInstance.StartTest();
}


Wouldn't you simply pass a pointer or reference to he B object?

class C 
{ 
public: 
    void DoSomethingWithB( B& b) 
    { 
        b.Greet( ); // will work fine 
    } 
}; 

class A 
{ 
public: 
 B b; // Not caring about visibility or bad class/variable names here 
 C c; 
 void StartTest( ) 
 { 
      c.DoSomethingWithB( b); 
 } 
};

If the DoSomethingWithB() function won't modify the passed in B instance, you should mark the reference const so it can be called with a const B object (for example if the owning A object happens to be const):

void DoSomethingWithB( B const& b);

You have a few options for how to pass the B object to the function:

  • as a reference (void DoSomethingWithB( B& b)) which will let the function modify the passed in object. Changes will be refelected in the object that's passed in.

  • as a const reference (void DoSomethingWithB( B const& b)) which won't let the function modify the passed in object (unless the constness is cast away - something which can lead to undefined behavior if done on an object the is truely const)

  • as a pointer or const pointer to a B object (void DoSomethingWithB( B* b) or void DoSomethingWithB( B const* pb) ). These have similar performance to passing by reference, but the function could be passed a NULL pointer which needs to be dealt with properly (by not dereferencing it in that case). Also, the call of the function would need to change slightly to pass the address of the B object:

    c.DoSomethingWithB( &b);
    
  • as a pass-by-value parameter (void DoSomethingWithB( B b)). This has difference that the function can do whatever it likes with theo bject passed in and it won't affect the originally passed object since the function is dealing with a copy. The disadvantage is that passing the parameter causes a copy to be made which might be expensive. You could also pass in a const value, but there's little to recommend that over passing a const reference.

Note that when chosing the parameter passing method, you should first chose based on the sematics of what you need the function to do (or not do). Worry about efficiency later. Always first design and code for correctness - worry about efficiency only after you have the design and code correct.


Change the functions to the following:

void DoSomethingWithB(B& b)
{
    b.Greet();
}

... and in A ...

c.DoSomethingWithB(b);


You can do it just as you said -- pass a pointer (or a reference) to B in to DoSomethingWithB():

class C
{
public:
    void DoSomethingWithB(B & bInstance)
    {
        bInstance.Greet( ); // should work fine!
    }
};

Then you'll invoke it like so:

class A
{
public:
    B b; // Not caring about visibility or bad class/variable names here
    C c;
    void StartTest( )
    {
        c.DoSomethingWithB( b );
    }
};

I'd suggest using the reference approach here rather than a pointer, since:

  1. Your object is an automatic class member, and
  2. Passing a null B object into the function is not meaningful in this case.


In class C, declare the method DoSomethingWithB() like this:

void DoSomethingWithB( B* b )
{
   b->Greet();
}

And in class A call it like this:

void StartTest()
{
    c.DoSomethingWithB( &b );
}

Since you mentioned pointers, I answered using pointers. In C++ however, you should try to use const references whenever you can. That would of course require a small change to the existing code:

void DoSomethingWithB( const B& b )
{
   b.Greet();
}

// and

void StartTest()
{
    c.DoSomethingWithB( b );
}


I can't access B from inside C

Instead of having C call methods in B, why not have C return information to the caller so it can do the operation?

When I hit these I've found it's because I've got my classes organized poorly. Usually if I rethink them the difficulty disappears with a new organization.


class C 
{ 
public: 
    C (B & b) : b(b) {}
    void DoSomethingWithB( ) 
    { 
        // ... b.Greet( ); Use b;
    } 
private:
    B & b;
}; 

class A 
{ 
public: 
 B b; // Declare b before c! 
 C c; 
 A() : c (b) {}
 void StartTest( ) 
 { 
      c.DoSomethingWithB( ); 
 } 
}; 
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜