Jump to content

Is this possible?

- - - - -

This topic has been archived. This means that you cannot reply to this topic.
9 replies to this topic

#1
roboticforest

roboticforest

    Programmer

  • Members
  • PipPipPipPip
  • 110 posts
I'm not at a computer that has a compiler, and I won't be for quite a while, but I have a question.

Will the following code work? Is what I'm trying to do here possible?

Note: The following is pseudo-code! It will not compile as is, and I wrote it in a slight hurry.

class Base{

// Class Manager is a friend.


public:

virtual Function = 0;


private:

  SecretFunction(int num){

    number = num;

    Function();

    return;

  }


protected:

int number;

} // end base


class Derived{

public:

  Function(){

    cout << number;

  }

} // end derived


class Manager{

  Store(Base object){

    object.SecretFunction(42);

    // Store the base class somewhere.

  }

} // end manager



main(){

  Derived D;

  Manager M;

  M.Store(D);

}


Dave

#2
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
I don't see a reason why you should not be able to do what you described.

One thing,


class Manager{

  [b]void[/b] Store([b]const[/b]Base[b]&[/b] object){

    object.SecretFunction(42);

    // Store the base class somewhere.

  }

} // end manager



And you should actually declare SecretFunction as virtual, Store as non-virtual

#3
roboticforest

roboticforest

    Programmer

  • Members
  • PipPipPipPip
  • 110 posts

Lance said:

I don't see a reason why you should not be able to do what you described.

Thank you. When I'm next at a compiler I'm going to give it a try, but at the moment I'm not sure when that'll be.

Lance said:

And you should actually declare SecretFunction as virtual, Store as non-virtual

Why should I make SecretFunction virtual?
Dave

#4
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
Never mind. I thought you were talking about something else.

And if I did not get you wrong again this time, you were asking something like virtual copy constuction, C++ don't allow constructors to be virtual, for a good reason, but you can still achieve what you want in an indirect way if you are prepared to put up with creating objects on heap, or some other restraints (such as same size for classes in the derivation tree, refer to my post: C++: how would you solve this problem).

The most general way, creating objects on heap, you can have a virtual clone() function that returns a (smarter) pointer to the objects you copy constructed on the heap, and than store the (smarter) pointer in the Manager object.



class B{

public:

    virtual ~B(){}

    virtual void doSomthing()=0;

    

private:

    virtual B* clone()const=0; 

   

};


class D : public B

{

public:

    B (int v=0): value(v){}

    B (const B& b): value(b.value){}


    virtual DoSomething()

    {

         std::cout<<value<<std::endl;

    }

    


private:

    // caller is responsible for delete'ing the return object

    // should use smarter pointer instead 

    //

    virutal B* clone()const{

           return new B(*this);

   }


   int value;

};


class Manager

{

public:

     ~Manager(){

           for(unsigned i=0; i<objects.size(); ++i)

                 delete objects[i];

     }

     void store(const Base& b){

            objects.push_back(b.clone());

     }


private:

    std::vector<Base *p> objects;

};



int main()

{

      Manager m;

      D d(100), d1(1000), d2(2000);


       m.store(d);

       m.store(d1);

       m.store(d2);

        //....

       return 0;

}


Edited by Lance, 19 January 2009 - 04:43 PM.
grammer


#5
roboticforest

roboticforest

    Programmer

  • Members
  • PipPipPipPip
  • 110 posts
Um... err... Sorry, I wasn't talking about making a copy of anything. I'm sorry if...

class Manager{

  Store(Base object){

    object.SecretFunction(42);

    // Store the base class somewhere.

  }

} // end manager

... threw you off.

It was for demonstrative purposes only. Ignore the fact that this class stores something, the purpose here is to show that class Manager is accessing a private function from some other class. Pretend that the function Store is whatever function you like.

I know I wasn't particularly clear with my original post, being in a hurry and all, but allow me to explain better what is in my head.

Class Base, and class Manager are a set in a library I'm trying to design, and as such I want Manager to have access to Base's private, and protected data.

People using the library inherit from Base and write code for Function.

class Base {

  public:

  virtual Function = 0;

}


class Derived inherits from class Base {

public:

  Function() {

    // Users put their code here.

  }

}

The goal here is that the newly derived class (creatively named Derived) has access to some important data which it inherited, but didn't have to set up. When an instance of Derived is handed to Manager, Manager will treat it like an instance of Base and access SecretFunction.

Store(Base object) {

  object.SecretFunction(42);

}

SecretFunction's job is to set up the protected data then call Function (the library user's code).

SecretFunction(int num) {

  number = num;

  Function();

  return;

}

Specifically, what I want to know is...

Can Manager access the private functions and the protected data in Base, even though it has an instance of Derived?

And,

Can SecretFunction make a call to Function in the setup I have here?

I think the answer is yes to both questions, but because I can't test it right now I don't know and need a bit of help.
Dave

#6
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts

Quote

Can Manager access the private functions and the protected data in Base, even though it has an instance of Derived?

Yes. It would not care whether the reference passed to it is actually of a derived object. Manager, as a friend, has access to SecretFunction, as secretFunction is virtual, it correctly locate it in the vtable and then call it. As the vtable is actually Derived vtable, the derivated version of SecretFunction get called.



Quote

Can SecretFunction make a call to Function in the setup I have here?

SecretFunction can call whatever functions it has access privilege. It would not even know there is a Manager class that's going to access it INDIRECTLY through the vtable, nor would it care.

#7
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts
However, it should be noted that Manager doesn't have access to Derived protect or private functions or data members. Eg, you can not:

void Manager::store(const Base& b)
{
    b.SecretFunction(); // OK, call through vptr

    const Derived * d=reinterpret_cast<const Derived*>(&b);
    if( d==NULL)
         return;
    d->data++; // illegal, no access privillege
    d->SecretFunction(); // illegal, no access privillege, even it's equivalent to 
                               // a previous call through const Base& b.
    d::SecretFunction(); // illegal, no access privillege.
}


#8
roboticforest

roboticforest

    Programmer

  • Members
  • PipPipPipPip
  • 110 posts

Lance said:

Manager, as a friend, has access to SecretFunction, as secretFunction is virtual...

:huh: So, even though SecretFunction is private, and can't be inherited, it needs to be virtual or it will not be called properly when Manager has an instance of Derived?

Lance said:

However, it should be noted that Manager doesn't have access to Derived protect or private functions or data members.

:) Yeah I know. That was a big part of my concern to begin with. I knew that friendship was not inherited, and I was worried that Manager would not be able to interact with Base properly if it actually had an instance of Derived.
Dave

#9
Lance

Lance

    Programming Professional

  • Members
  • PipPipPipPipPip
  • 276 posts

Quote

So, even though SecretFunction is private, and can't be inherited, it needs to be virtual or it will not be called properly when Manager has an instance of Derived?

You got it. If SecretFunction is not virtual, the Base version will always got called.

Quote

I was worried that Manager would not be able to interact with Base properly if it actually had an instance of Derived.
No problem at all, as long as the method is virtual.

#10
roboticforest

roboticforest

    Programmer

  • Members
  • PipPipPipPip
  • 110 posts
Thanks Lance. You were a lot of help.

:thumbup1:
Dave