forward declaration & virtual member function return derived class

Discussion in 'C++' started by kepeng@gmail.com, Jul 2, 2008.

  1. Guest

    There are 2 abstract base classes:

    class IB;
    class IA
    {
    //...
    public:
    virtual IB* GetB() = 0;
    }

    class IB
    {
    //...
    public:
    virtual IA* GetA() = 0;
    }

    Then, this is derived classes:

    class CB; //#1
    class CA : public IA
    {
    //...
    public:
    CB* GetB(); //#2
    }
    class CB : public IB
    {
    //...
    public:
    CA* GetA(); //#3
    }

    The question is, the declaration do not work.
    In C++, the overrided function can return a class which is public
    derived from the return type of the function in base class.
    When the function #2 returns IB*, it is OK. #3 is OK, too.
    But, when #2 returns CB*, the compiler says something like "CB is not
    derived from IB".
    At #1, I can not declare like this:
    class CB : public IB;
    The syntax is not passed.

    So, what can I do?
    There is cycle dependence, but I do not care of the dependence: CA and
    CB is almost in a single .cpp file.
     
    , Jul 2, 2008
    #1
    1. Advertising

  2. Re: forward declaration & virtual member function return derivedclass

    On 2 Jul., 19:46, "" <> wrote:
    > There are 2 abstract base classes:
    >
    > class IB;
    > class IA
    > {
    > //...
    > public:
    > virtual IB* GetB() = 0;
    >
    > }
    >
    > class IB
    > {
    > //...
    > public:
    > virtual IA* GetA() = 0;
    >
    > }
    >
    > Then, this is derived classes:
    >
    > class CB; //#1
    > class CA : public IA
    > {
    > //...
    > public:
    > CB* GetB(); //#2}
    >
    > class CB : public IB
    > {
    > //...
    > public:
    > CA* GetA(); //#3
    >
    > }
    >
    > The question is, the declaration do not work.
    > In C++, the overrided function can return a class which is public
    > derived from the return type of the function in base class.
    > When the function #2 returns IB*, it is OK. #3 is OK, too.
    > But, when #2 returns CB*, the compiler says something like "CB is not
    > derived from IB".
    > At #1, I can not declare like this:
    > class CB : public IB;
    > The syntax is not passed.
    >
    > So, what can I do?
    > There is cycle dependence, but I do not care of the dependence: CA and
    > CB is almost in a single .cpp file.


    you need to give them different names, because you cant overload a
    function by just changing it's return-type:

    class CB : public IB
    {
    public:
    CA* _GetA() {return static_cast<CA*>(GetA());};
    private:
    IA* GetA();
    };
     
    .rhavin grobert, Jul 2, 2008
    #2
    1. Advertising

  3. Guest

    Re: forward declaration & virtual member function return derivedclass

    On 2 Jul, 18:46, "" <> wrote:
    > class IA
    > {
    >     //...
    > public:
    >     virtual IB* GetB() = 0;
    > }
    >
    > class CA : public IA
    > {
    >     //...
    > public:
    >     CB* GetB(); //#2}


    Your problem, as rhavin grobert has also pointed out, is that in one
    case GetB returns an IB* and in the other it returns a CB*. He has
    suggested you use functions with different names, but that doesn't
    seem to me to be quite what you want. I think you need to decide
    whether GetB will return a CB* for all classes derived from IA, or
    not. If you're always going to return a CB* then change the
    declaration in IA. If not, change the declaration in class IA so that
    it says GetB returns an IB*. Since CB is derived from IB, a pointer to
    an IB can hold any value that a pointer to a CB can, so the values can
    be passed quite happily.

    If you really need the return type of GetB to be different for
    different classes, you may need to have differently-named functions,
    or to have another think about your class structure.

    Hope that helps.
    Paul.
     
    , Jul 2, 2008
    #3
  4. Re: forward declaration & virtual member function return derivedclass

    On Jul 2, 1:46 pm, "" <> wrote:
    > There are 2 abstract base classes:
    >
    > class IB;
    > class IA
    > {
    > //...
    > public:
    > virtual IB* GetB() = 0;
    >
    > }
    >
    > class IB
    > {
    > //...
    > public:
    > virtual IA* GetA() = 0;
    >
    > }
    >
    > Then, this is derived classes:
    >
    > class CB; //#1
    > class CA : public IA
    > {
    > //...
    > public:
    > CB* GetB(); //#2}
    >
    > class CB : public IB
    > {
    > //...
    > public:
    > CA* GetA(); //#3
    >
    > }
    >
    > The question is, the declaration do not work.


    You are missing semicolons at the end of the class definitions. Test
    your
    code before posting it.

    > In C++, the overrided function can return a class which is public
    > derived from the return type of the function in base class.
    > When the function #2 returns IB*, it is OK. #3 is OK, too.
    > But, when #2 returns CB*, the compiler says something like "CB is not
    > derived from IB".
    > At #1, I can not declare like this:
    > class CB : public IB;
    > The syntax is not passed.


    As far as I can tell, you cannot use covariance in this case. Either
    return a
    pointer to the interface or change your design so that you do not have
    a
    cyclic dependency.

    --
    Jonathan Mcdougall
     
    Jonathan Mcdougall, Jul 2, 2008
    #4
  5. Guest

    Re: forward declaration & virtual member function return derivedclass

    On Jul 2, 11:04 am, ".rhavin grobert" <> wrote:
    > On 2 Jul., 19:46, "" <> wrote:
    >
    >
    >
    > > There are 2 abstract base classes:

    >
    > > class IB;
    > > class IA
    > > {
    > > //...
    > > public:
    > > virtual IB* GetB() = 0;

    >
    > > }

    [...]
    > > class CA : public IA
    > > {
    > > //...
    > > public:
    > > CB* GetB(); //#2}


    [...]

    > you need to give them different names, because you cant overload a
    > function by just changing it's return-type:


    Yes but this is not overloading. Because of that 'virtual' above, CA
    is overriding the same function, and C++ does support covariant return
    types.

    The problem here is that CA and CB cannot both see the definition of
    the other at the same time. It must be possible to solve by returning
    proxy classes instead of plain IB* and CB*.

    Ali
     
    , Jul 3, 2008
    #5
  6. Guest

    Re: forward declaration & virtual member function return derivedclass

    On Jul 2, 10:46 am, "" <> wrote:
    > There are 2 abstract base classes:
    >
    > class IB;
    > class IA
    > {
    >     //...
    > public:
    >     virtual IB* GetB() = 0;
    >
    > }
    >
    > class IB
    > {
    >     //...
    > public:
    >     virtual IA* GetA() = 0;
    >
    > }
    >
    > Then, this is derived classes:
    >
    > class CB; //#1
    > class CA : public IA
    > {
    >     //...
    > public:
    >     CB* GetB(); //#2}
    >
    > class CB : public IB
    > {
    >     //...
    > public:
    >     CA* GetA(); //#3
    >
    > }
    >
    > The question is, the declaration do not work.
    > In C++, the overrided function can return a class which is public
    > derived from the return type of the function in base class.
    > When the function #2 returns IB*, it is OK. #3 is OK, too.
    > But, when #2 returns CB*, the compiler says something like "CB is not
    > derived from IB".
    > At #1, I can not declare like this:
    > class CB : public IB;
    > The syntax is not passed.
    >
    > So, what can I do?
    > There is cycle dependence, but I do not care of the dependence: CA and
    > CB is almost in a single .cpp file.


    Try using proxy classes (Holders below) that allow covariance by being
    fully defined where used:


    class IA;

    class IAHolder
    {
    IA * ia_;
    };

    class CA;

    class CAHolder : public IAHolder
    {
    CA * ca_;
    };


    class IB;

    class IBHolder
    {
    IB * ia_;
    };

    class CB;

    class CBHolder : public IBHolder
    {
    CB * ca_;
    };


    class IA
    {
    //...
    public:
    virtual ~IA()
    {}
    virtual IBHolder * GetB() = 0;

    };


    class IB
    {
    //...
    public:
    virtual ~IB()
    {}
    virtual IAHolder * GetA() = 0;

    };


    class CB; //#1
    class CA : public IA
    {
    //...
    public:
    CBHolder * GetB()
    {
    return 0;
    }
    };


    class CB : public IB
    {
    //...
    public:
    CAHolder * GetA()
    {
    return 0;
    }
    };

    int main()
    {
    CA ca;
    CB cb;
    }

    Ali
     
    , Jul 3, 2008
    #6
  7. Guest

    Re: forward declaration & virtual member function return derivedclass

    On 2 Jul, 20:57, wrote:
    > On 2 Jul, 18:46, "" <> wrote:
    >
    > > class IA
    > > {
    > >     //...
    > > public:
    > >     virtual IB* GetB() = 0;
    > > }

    >
    > > class CA : public IA
    > > {
    > >     //...
    > > public:
    > >     CB* GetB(); //#2}

    >
    > Your problem, as rhavin grobert has also pointed out, is that in one
    > case GetB returns an IB* and in the other it returns a CB*. He has
    > suggested you use functions with different names, but that doesn't
    > seem to me to be quite what you want. I think you need to decide
    > whether GetB will return a CB* for all classes derived from IA, or
    > not. If you're always going to return a CB* then change the
    > declaration in IA. If not, change the declaration in class IA so that


    My mistake - this should say ... change the declaration in class CA
    so that ...

    > it says GetB returns an IB*. Since CB is derived from IB, a pointer to
    > an IB can hold any value that a pointer to a CB can, so the values can
    > be passed quite happily.
    >
    > If you really need the return type of GetB to be different for
    > different classes, you may need to have differently-named functions,
    > or to have another think about your class structure.
    >
    > Hope that helps.
    > Paul.
     
    , Jul 3, 2008
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. qazmlp
    Replies:
    1
    Views:
    619
    Jonathan Turkanis
    Feb 15, 2004
  2. Xiangliang Meng
    Replies:
    2
    Views:
    416
    Jack Klein
    Jun 21, 2004
  3. Siemel Naran
    Replies:
    4
    Views:
    818
    Micah Cowan
    Jan 12, 2005
  4. Replies:
    1
    Views:
    407
    myork
    May 23, 2007
  5. Alex Shen
    Replies:
    5
    Views:
    427
    Alex Shen
    Oct 30, 2010
Loading...

Share This Page