🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c++
Article #218

Declarations of Member Functions Outside Class Definitions

#218
From: Scott Meyers
Date: Wed, 01 Aug 1990 20:05
144 lines
4636 bytes
Proposed:

  That it be possible to declare member functions outside of class
  declarations exclusively for the purpose of later friend declarations.

Example:

  class Example;                      // currently legal
  void Example::f(int);               // currently illegal, but would be ok

  class Sample {
    friend void Example::f(int);      // currently legal, provided class
                                      // Example has been defined
    function()
      {
        void (Example::*pmf)(int) =
          Example::f;                 // currently illegal and would
                                      // remain illegal
      }
  };

Motivation:

  Such a change would make it easier to declare certain friend
  relationships without having to embed #include directives in the middle
  of header files.

  As an example, consider the following classes:

    - WithFriend, which has a private int member and which declares the
      constructor for class Derived as a friend.

    - Base, which has a constructor that takes an int as an argument.

    - Derived, a derived class of Base, that has a constructor that takes a
      WithFriend reference as an argument and initializes the Base
      constructor with the private int member of the referenced WithFriend.

  This must currently be declared as follows:

    class Base {
    protected:
      Base(int baseArg) {}
    };

    class WithFriend;

    class Derived: public Base {
    public:
      Derived(WithFriend& derivedArg);
    };

    class WithFriend {
      friend Derived::Derived(WithFriend&);
    private:
      int privateMember;
    };

    inline Derived::Derived(WithFriend& derivedArg)
    : Base(derivedArg.privateMember) {}

  With the proposed change, it could be declared as follows:

    class WithFriend;
    extern Derived::Derived(WithFriend&);            // currently illegal

    class WithFriend {
      friend Derived::Derived(WithFriend&);
    private:
      int privateMember;
    };

    class Base {
    protected:
      Base(int baseArg) {}
    };

    class Derived: public Base {
    public:
      Derived(WithFriend& derivedArg)
        : Base(derivedArg.privateMember) {}
    };

  The latter declaration is a little cleaner, in my opinion, because all
  the forward declarations are at the beginning and there is no need to
  separate the inline body of the Derived constructor from the class
  declaration, but that's hardly compelling.  The important situation --
  and the common one -- is when WithFriend is declared in a different file
  from Base and Derived, say WithFriend.h and Base.h, respectively.  Then
  the declaration must be as follows:

    class Base {
    protected:
      Base(int baseArg) {}
    };

    class WithFriend;

    class Derived: public Base {
    public:
      Derived(WithFriend& derivedArg);
    };

    #include "WithFriend.h"

    inline Derived::Derived(WithFriend& derivedArg)
    : Base(derivedArg.privateMember) {}

  In this case the #include directive must occur in the middle of the file,
  contrary to intuition and common convention for #include file usage.
  With the proposed change, the #include directives need only occur at the
  top of files:

    class WithFriend;                               // file WithFriend.h
    extern Derived::Derived(WithFriend&);

    class WithFriend {
      friend Derived::Derived(WithFriend&);
    private:
      int privateMember;
    };

    -------------------------------------------------------------------------

    #include "WithFriend.h"                         // file Base.h
    class Base {           
    protected:
      Base(int baseArg) {}
    };

    class Derived: public Base {
    public:
      Derived(WithFriend& derivedArg)
        : Base(derivedArg.privateMember) {}
    };

  Note that allowing member functions to be declared but not used is
  similar to the standard C++ facility for allowing class names to be
  declared but no objects of those classes to be used prior to class
  definition.


Scott
sdm@cs.brown.edu
Technical Details
Message-ID: <46393@brunix.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!mailrus!umich!samsung!sdd.hp.com!decwrl!uunet!brunix!sdm

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!utgpu!news-server.csri.toronto.edu!mailrus!umich!samsung!sdd.hp.com!decwrl!uunet!brunix!sdm
From: sdm@cs.brown.edu (Scott Meyers)
Newsgroups: comp.std.c++
Subject: Declarations of Member Functions Outside Class Definitions
Message-ID: <46393@brunix.UUCP>
Date: 1 Aug 90 20:05:31 GMT
Sender: news@brunix.UUCP
Reply-To: sdm@cs.brown.edu (Scott Meyers)
Organization: Brown University Department of Computer Science
Lines: 144