user1696715
user1696715

Reputation:

Class namespace?

Is it me or the implementation of object oriented paradigm in C++ is missing the concept of class namespace?

Here is an example of what I mean:

Document { Header {} Body {} Footer {} }

Document is an object that can have a header, body, and footer.

A straight forward way to address such object and its elements from external namespace is

Is there a way to achieve such naming structure in C++ without imposing a restriction on the definition of Document class?

1) namespace Document { ... }

This case requires an object class inside its own namespace and using Document::Document seems redundant and unintended.

2) namespace Document { class ... } typedef Document::Document document;

This case gives document and Document::{part}, which in case sensitive language may seem weird and unrelated.

3) class Document { class ... };

This case requires including Document header in definition of every nested class and doesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.

4) class document { class ... }; class Document : public document {}

This case is close to what is intended but costs an extra class and inheritance.

!) Ideally, what I'd like to have is

namespace class Document {

class Header;
class Body;
class Footer;

class Document; // linked with the parent namespace as with its own name space

}

Document doc; // ok, resolves Document as a class
Document::{Part} docPart; // ok, resolves Document as namespace

.) Is there any other reasonable way to achieve what is intended without unreasonable extra cost?

I'm also not exactly sure why such trivial things are not a standard way to do it. :/ Any specific reason?

--- clarification ---

To address some of the raised questions,

"What is it useful for?" 1) Plain language 2) Transparent mapping from a language construct to an object's abstract model and vice versa.

"Why would one want to derive an object from its parts?" Not every entity introduced by an object has to be its part. It can be its essence, for example. E.g.:

Document { Skeleton{} Parts { Header {} Body {} Footer {} } }

--- abstract framework ---

Think of an object as a module whose definition may use external symbols and introduce some of its own along with the definition of its own logical entity, to which they should remain related since it introduces them.

--- point ---

The whole module is a definition of an object. It would be nice to be able to use it as such without any additional linguistic ridicules.

=== resolution ===

Thank you for your feedback.

Until there is a way in C++ to link a namespace name to a class, I guess I'll use the

ObjectName { ... Object {} } -> ObjectName::Object, ObjectName::Part

construct in such cases. It may be not as short as I'd like to, but at least transparent enough, with no extra cost, and can be used with forward declarations.

Upvotes: 0

Views: 1161

Answers (6)

James Kanze
James Kanze

Reputation: 153899

It's not totally clear to me how much you want to expose the nested classes, but if they are part of Document, they probably should be nested classes. Your example of what you mean, at the start of your code, is exactly how one would do this in C++:

class Document
{
public:  //  or not?
    class Header
    {
    };
    class Body
    {
    };
    class Footer
    {
    };
};

About the only objection I can see is that implementation files only concerned with Document::Header must include the entire Document class definition, but I don't think this is a major problem; if Document::Header really isn't independent, then it seems reasonable to require this. With regards to your second objection to this solution: you never want to make an object derive from its parts: a Document hasA Header; it isn't an isA relationship.

If it does make sense for Header et al to be used separately, then the best solution is to define them outside of the Document class, either giving them more descriptive names (e.g. DocumentHeader) or wrapping them in a special namespace (e.g. namespace DocumentParts). Depending on their relationship with Document, it might make sense to use typedef in Document so that they can be referred to as either DocumentParts::Header or Document::Header.

Upvotes: 0

Konrad Rudolph
Konrad Rudolph

Reputation: 545508

Just because a Document object contains a Header object doesn’t mean that the Header class should be contained in the Document class. At least, that’s not usually done.

I would nest classes only in rare instances; namely, when the nested class is an implementation detail of the outer class, and isn’t exposed to the outside world (but even then it’s common to forego nesting).

This, by the way, is independent of C++: classes in general are rarely nested except to hide implementation details. Frameworks to model object relations as in your case wouldn’t normally use nesting. Instead, you might have something like this:

namespace Html {
    class Document;
    class Header;
    class Body;
    // …
}

C++ in particular uses flat namespace hierarchies but the above would equally apply to C# or Java.

Finally, to explicitly address your introductory question:

Is it me or the implementation of object oriented paradigm in C++ is missing the concept of class namespace?

C+ has this concept to the same extent as other modern OO languages: a class forms a namespace for the purpose of name lookup so you can achieve what you want. But for the reason mentioned above I don’t think it’s a particularly desirable goal.

Upvotes: 1

tenfour
tenfour

Reputation: 36896

3) class Document { class ... };

This case requires including Document header in definition of every nested class and doesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.

No, this design is what makes the most sense. I don't understand what you think the difference would be between class and namespace class.

class Document
{
public:
    class Header
    {
    };

    Header m_header;

    class Body
    {
    };

    Body m_Body;
};

What's wrong with this design? You access the types via Document::Header. You access via instances like myDocument.m_header.

The only inherent oddness is that you can't name a type and member variable the same, but there are plenty of ways around that and it's a superficial restriction really.

Upvotes: 1

Joris Timmermans
Joris Timmermans

Reputation: 10968

Your third option - using nested class declarations / definitions, will get you the ideal scope resolution as you want (though it will not involve a single namespace).

class Document 
  {
  public:
    class Header
      {
      // Header class declaration here
      };

    class Body
      {
      // Body class declaration here
      };

   class Footer
      {
      // Footer class declaration here
      };

    // Document declaration here.
  };

Your concerns with that option are:

Requires including Document header in definition of every nested class

Yes - the nested classes are inextricably linked to the surrounding class, their implementations will depend on the definition of the surrounding class because it contains the definitions of the nested classes. This is unavoidable.

Dpesn't allow to make the final object be a derivative of its parts, since they are defined within its own scope.

What you are trying to do seems to make very little logical sense - you are trying to define something based on its own parts, which is a circular definition. What are you trying to achieve by deriving Document from Header, Body or Footer?

The final line of your question suggests that you find your desired functionality "trivial", but in my opinion and experience it is far from trivial. You seem to be conflating a namespace and a class because of syntactical similarities, but they are entirely different concepts. You have to separate the two in your mind, they have very little overlap besides some scoping effects and scope resolution syntax. Your "Document" must be either a namespace and a class. Pick one ;) (technically it's actually possible to have both a namespace Document and a class Document, but this is likely to be a source of confusion. )

Upvotes: 6

Caleb
Caleb

Reputation: 124997

Your first case does exactly what you say you want. There's nothing redundant about Document::Document -- it refers to the Document class in the Document namespace. There might very well be a Document class in the XML namespace, and another one in the MyCompany namespace.

Your second case looks like an attempt to essentially defeat the purpose of using namespaces. If you don't want to use a namespace, don't -- just use the global (unspecified) namespace and risk collisions. If you only want to avoid the Document:: part in the code that's related to your Document class, add a using namespace Document directive in that code.

Upvotes: 2

Mark Garcia
Mark Garcia

Reputation: 17708

You just enclose the part classes within the Document class.

class Document {
public:
   class Header;
   class Body;
   class Footer;
};

You can validly use this:

Document myDoc;   // Type Document
Document::Header myHeader;

Upvotes: 1

Related Questions